65.9K
CodeProject 正在变化。 阅读更多。
Home

垂直滚动文本框(动画关于框)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.69/5 (9投票s)

2013年11月2日

CPOL

5分钟阅读

viewsIcon

27616

downloadIcon

1065

一个用于显示垂直滚动文本的用户控件。以关于框为例。

引言

本文档解释了该用户控件的用法和源代码。

背景

几年前,我需要一个能够垂直滚动文本的控件。我需要它用于一个“关于”表单来展示一些功劳。我在 planet-source-code.com 网站上找到了一位名叫 Paul Pickert 的作者提供的基本解决方案。目前我的需求发生了变化,我不得不增强这个基本解决方案的功能。

请耐心谅解语言上的错误,因为英语不是我的母语。

使用代码

我将文章分为两部分。第一部分解释了开发者如何使用该控件。第二部分讲解了代码结构和其背后的基本原理。

第一部分: 控件用法

属性设置

现在您可以设置属性了。除了用户控件的已知属性外,您还会发现两个新属性:MessageMessageTimer。它们也可能在属性页的“扩展属性”类别下找到。

这两个属性分别代表用户控件的两个子控件。Message 代表一个标签控件,MessageTimer 代表一个标准的计时器控件。使用这些子控件的属性以及用户控件的主属性来设计您的 animatedTexbox 控件。

  • Message.Text:包含要滚动的文本,行可以使用 vbCRLF 分隔
  • Message.TextAlign:对齐滚动文本
  • MessageTimer.Interval:滚动间隔(以毫秒为单位)。50毫秒应该是不错的选择。
  • MessageTimer.Enabled:启动/停止滚动

就是这样!

准备承载该控件的 Windows 窗体

现在,我们必须在父窗体加载时初始化该控件。我们在窗体的加载事件中完成此操作,请参阅代码列表区域。

Private Sub frmAbout_Load(sender As Object, e As EventArgs) Handles MyBase.Load
   ' define the text for the message. Use vbCrlf for carriage return/new line
   Dim strMessage As String = "Copyright fremde Programm Controls:" & vbCrLf
   strMessage = strMessage & "(Taken form codeproject.com)" & vbCrLf & vbCrLf
   strMessage = strMessage & "ImageView Control by Jordy Ruiter" & vbCrLf
   strMessage = strMessage & "MultiColCombobox by Gismo" & vbCrLf
   strMessage = strMessage & "CustValidatorTextbox by Vivek Bhatnagar" & vbCrLf
   ' ini the control property values
   animTextBox1.Message.Text = strMessage ' set the message text
   
    ' set no TextAlign to use the default center alignment
    ' set no timer interval to use the default value of 50 milliseconds
    animTextBox1.MessageTimer.Enabled = True 'start animation
End Sub 

第二部分:“控件代码”

  1. 开始创建一个新项目,选择 Visual Basic 作为语言,然后选择 Windows 用户控件。
  2. 重命名用户控件,并将其命名为 animTextbox。必须使用此名称,否则在使用工具箱图标的辅助类时会出现冲突(请参阅下面的说明)。
  3. 创建一个 16x16 像素的位图(bmp)作为工具箱项的位图,并将其文件放在项目文件夹中。文件名必须是 animToolbox.bmp
  4. 在设计器中打开用户控件。
  5. 将一个面板控件拖放到上面,并将其 Dock 属性设置为 fill。将其命名为 Panel1
  6. 将一个标签控件拖放到面板控件上,并将其位置设置为面板的底部,将其命名为 labelMessage
  7. 打开用户控件的代码窗口。

为了提高可读性,我将代码分成了区域。

在用户控件的代码头部,我们必须定义对 System.ComponentModel 的导入引用。我们需要这个导入来定义用户控件的扩展属性。

' ### neccessary Imports
Imports System.ComponentModel   

接下来,我们必须定义工具箱图标的代码。这段代码与打开的类语句相关联。该代码引用了您必须添加到用户控件项目中的两个类。这些辅助类用于在 Visual Studio 工具箱中正确显示图标。请按原样使用它们。本文档不解释这些类的内容,因为它们只是辅助类。

 ' set the Toolbox Bitmap Icon 
 ' this done by the classes classToolboxIcon and clsTypeConverter
 <ToolboxItem(True)> <ToolboxBitmap(GetType(animTextBoxToolboxitem), "animTextBox.bmp")> _
Public Class animTextBox 

在打开的类语句下的下一行,我们定义了一些全局变量,并且为了动画效果,我们需要一个计时器对象。

 #Region "INI Variables, objects, events" ' ################ 
 ' ## Property variables 
 Private _Msg As Label = LabelMessage
 Private _TMR As Timer
 ' ## other variables
 Private intPosition = 0
 ' ## Private objects
 Private WithEvents objTimer1 As New Timer ' use withevents to get timer tick event
#End Region  

我们将 _Msg_TMR 变量定义为控件。这个简单的技巧使我们能够使这些控件的属性通过用户控件透明化。这样,控件的用户就可以修改其属性。如果我们不这样做,用户控件只会显示其自身的属性。

现在我们可以专注于定义一些额外的属性来增强用户控件的标准属性。

 #Region "extended usercontrol properties" ' ###########

' public all label object properties to be able to change them
<Browsable(True), Description("Textlabel of the message to hold the message text") _
, Category("extended Properties")> _
Public Property Message As Label
 Get
     Return LabelMessage
 End Get
 Set(value As Label)
     _Msg = value
 End Set
End Property

' public all timer object properties to be able to change them
<Browsable(True), Description("Timer for animation of the message") _
, Category("extended Properties")> _
Public Property MessageTimer As Timer
 Get
     Return objTimer1
 End Get
 Set(value As Timer)
     _TMR = value
 End Set
End Property
#End Region 

第一个属性 Message 包含用户控件的子控件对象 labelMessage,属性 MessageTimer 包含内部计时器对象。

下一步是定义控件的事件。

在加载事件中,我们将属性变量 _Msg_TMR 与控件关联起来。至少,我们调用内部函数 ALignText() 来确保滚动文本按要求对齐。

 #Region "Control events" '#########################
' Event control loads
' set startup values
Private Sub animTextBox_Load(sender As Object, e As EventArgs) Handles Me.Load
 intPosition = Panel1.Height + 25 ' set initial start position
 _TMR = objTimer1 ' load property value with timer object
 _Msg = LabelMessage ' load property value with label object
 ' 50 (Milliseconds) should be a good timer.interval value for a smooth
 ' animation
 objTimer1.Interval = 50
 ALignText() ' reset text alignment
End Sub 

为了管理文本的动画,我们使用计时器滴答事件。为了动画/滚动文本,我们首先将 labelMessage.Top 位置设置在 Panel1 控件的外部(下方)。因此,它最初是不可见的。

每次计时器滴答,我们就从 Top 位置值中减去 1,以强制 labelMessage 控件被绘制到比 Panel1 控件高 1 个点的位置。这看起来就像向上滚动。我们这样做,直到整个 labelMessage 控件完全位于 Panel1 控件的外部(上方)。因此,labelMessage 控件是不可见的。

当我们到达这一点时,我们将 labelMessage 控件的位置重置回其初始值。这模拟了无限滚动的文本。

最后,我们调用 Application.DoEvents 来释放所有待处理的应用程序任务,这些任务可能在计时器滴答任务期间被挂起。

' Event timer tick = next animation step  
Private Sub objTimer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)  _
Handles objTimer1.Tick 
 On Error Resume Next
 ' if there is no message text stop timer
 If LabelMessage.Text = "" Then
     objTimer1.Enabled = False
 Else
     ' increase/scroll label top point
     intPosition = intPosition - 1
     ' check if label is completly scrolled
     ' if yes reset label top position below panel to restart animation
     If intPosition = (LabelMessage.Height + 25) * -1 Then
         LabelMessage.Top = Me.Height + 25
         intPosition = LabelMessage.Top
     End If
     ' show label at new postion
     LabelMessage.Top = intPosition
 End If
 ALignText() ' make shure text alignment
 Application.DoEvents() ' give other app tasks a chance to work
End Sub 

为了让应用程序用户有机会停止滚动(可能为了阅读静态文本),我们通过将鼠标光标指向用户控件区域来提供这种可能性。为此,我们使用 Panel1 控件的 Mouse.Enter 和 Mouse.leave 事件。' 事件光标进入/在面板/控件区域内

' stop the animation and set text to top 
Private Sub Panel1_MouseEnter(sender As Object, e As EventArgs) Handles Panel1.MouseEnter
     ' stop the timer and set the label.top position to the top of the panel
     objTimer1.Enabled = False
     LabelMessage.Top = Me.Height - 50
     ALignText()
End Sub

' Event cursor is leaving panel/control area
' restart the animation
Private Sub Panel1_MouseLeave(sender As Object, e As EventArgs) Handles Panel1.MouseLeave
 ' reset the label.top position below the panel to restart animation
 LabelMessage.Top = Me.Height + 25
 intPosition = LabelMessage.Top
 objTimer1.Enabled = True
End Sub  
#End Region 

呼,我们快要完成这项工作了。我们必须定义 AlignText() 函数。这将把 labelMessage 控件放到 Panel1 控件的左边界(左对齐)或者将其居中。

  #Region "Private Functions/Subs" '#################
     ' Align the Textposition
     Sub ALignText()
         On Error Resume Next
         ' if the TextAlign property of the text label is set to left
         ' put the text label control to the left border of its parent (panel)
         If LabelMessage.TextAlign = ContentAlignment.TopLeft Then
             LabelMessage.Left = 1
         Else ' if not always center the text label (panel dock property is set to fill)
             Dim intW As Integer = Int(Me.Width / 2)
             Dim intW1 As Integer = Int(LabelMessage.Width / 2)
             Dim intDiff = intW - intW1
             If intDiff < 0 Then intDiff = 0 ' avoid negativ values
             LabelMessage.Left = intDiff
         End If
     End Sub 
 #End Region 
 end class

您准备好了!编译该项目,并在您的下一个项目中使用创建的(animTextbox 控件)DLL。

要下载包含 Visual Studio 项目的 ZIP 文件,请使用此链接: 下载 VerticalText.zip

关注点

我在互联网上搜索过,找到了一些解决方案。在大多数情况下,它们使用 GDI 功能来绘制文本。我尝试过它们,遇到了常见的闪烁问题。然后我回忆起几年前找到的 Paul Pickert 的解决方案,这是一个非常简单的想法。最终我学到了,有时候简单的解决方案是最好的方法。

历史

还没有更新,因为这是初始版本。如果您发现任何错误或有改进的建议,请随时发表评论。

© . All rights reserved.