This pages show you how to use the VB wizard to create a custom ticker control. It illustrates the VB wizard in detail, how properties can be dispatched to existing controls within your own control, and how completely new properties can be created. It also shows an interesting (even though its simple) new type of control! The actual ticker example is from Chapter 5 of Custom Controls Library by Rod Stephens (O'Reilly Press).
We assume that you're going to know how to start up VB and start a new project. Its probably best if you have already tried the HelloWorld example.
Also,
download
the source if you want to see it work before you do it yourself. We will
cover:
![]() Figure 1: new project dialog |
![]() Figure 2: project properties dialog |
![]() Figure 3: the control layout |
![]() Figure 4: how to find the illusive VB ActiveX Control Interface Wizard |
| BackColor | Property |
| BorderStyle | Property |
| Click | Event |
| DblClick | Event |
| Enabled | Property |
| Font | Property |
| ForeColor | Property |
![]() Figure 5: select interface members dialog |
| AutoSize | Property |
| Caption | Property |
| Interval | Property |
| RepeatSpacing | Property |
| XChange | Property |
![]() Figure 6: create some custom interface members! |
| Public Name | Maps to Control | Maps to Member |
| AutoSize | (none) | |
| BackColor | UserControl | BackColor |
| BorderStyle | UserControl | BorderStyle |
| Caption | (none) | |
| Click | UserControl | Click |
| DblClick | UserControl | DblClick |
| Enabled | (none) | |
| Font | UserControl | Font |
| ForeColor | UserControl | ForeColor |
| Interval | tmrTicker | Interval |
| RepeatSpacing | (none) | |
| XChange | (none) |
![]() Figure 7: set mapping for the members of your control |
| Public Name | Data Type | Default Value | Run Time | Design Time | Description |
| AutoSize | Boolean | 0 | R/W | R/W | determines whether the control resizes itself to fit the text displayed |
| Caption | String | R/W | R/W | the text displayed | |
| Enabled | Boolean | 0 | R/W | R/W | determines whether the control is enabled to scroll text |
| RepeatSpacing | Integer | 0 | R/W | R/W | the distance in pixels between occurrences of the repeating caption |
| XChange | Integer | 0 | R/W | R/W | the distance by which the text is moved when the interval expires |
![]() Figure 8: Set the attributes for the members of your control |
![]() Figure 9: and we are done. |
Okay, the complete code is spat out here. Here's how to read it:
Option Explicit
' Enumerated data values.
Enum tick_BorderStyle
None_tick_BorderStyle = 0
Fixed_Single_tick_BorderStyle = 1
End Enum
'Default Property Values:
Const m_def_RepeatSpacing = 4
Const m_def_XChange = 1
Const m_def_AutoSize = False
Const m_def_Caption = "Ticker..."
Const m_def_Enabled = False
'Property Variables:
Dim m_RepeatSpacing As Integer
Dim m_XChange As Integer
Dim m_AutoSize As Boolean
Dim m_Caption As String
Dim m_Enabled As Boolean
'Event Declarations:
Event Click() 'MappingInfo=UserControl,UserControl,-1,Click
Event DblClick() 'MappingInfo=UserControl,UserControl,-1,DblClick
Dim skip_redraw As Boolean
Dim X As Single
Dim CaptionWidth As Single
Public Property Get AutoSize() As Boolean
AutoSize = m_AutoSize
End Property
Public Property Let AutoSize(ByVal New_AutoSize As Boolean)
m_AutoSize = New_AutoSize
PropertyChanged "AutoSize"
SizeControl ' Resize if necessary.
End Property
'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES!
'MappingInfo=UserControl,UserControl,-1,BackColor
Public Property Get BackColor() As OLE_COLOR
BackColor = UserControl.BackColor
End Property
Public Property Let BackColor(ByVal New_BackColor As OLE_COLOR)
UserControl.BackColor() = New_BackColor
PropertyChanged "BackColor"
DrawText ' Redraw.
End Property
'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES!
'MappingInfo=UserControl,UserControl,-1,BorderStyle
Public Property Get BorderStyle() As tick_BorderStyle
BorderStyle = UserControl.BorderStyle
End Property
Public Property Let BorderStyle(ByVal New_BorderStyle As tick_BorderStyle)
UserControl.BorderStyle() = New_BorderStyle
PropertyChanged "BorderStyle"
SizeControl ' Resize if necessary.
End Property
Public Property Get Caption() As String
Caption = m_Caption
End Property
Public Property Let Caption(ByVal New_Caption As String)
m_Caption = New_Caption
PropertyChanged "Caption"
CaptionWidth = TextWidth(m_Caption)
If CaptionWidth > 0 And Ambient.UserMode Then
tmrTicker.Enabled = m_Enabled
Else
tmrTicker.Enabled = False
End If
SizeControl ' Resize if necessary.
DrawText ' Redraw.
End Property
Private Sub DrawText()
' Do nothing if we're loading.
If skip_redraw Then Exit Sub
' Start from scratch.
Cls
' Do nothing if the text takes up no room.
If CaptionWidth <= 0 Then Exit Sub
' Draw the text.
CurrentX = X
CurrentY = 0
Do While CurrentX < ScaleWidth
Print m_Caption;
CurrentX = CurrentX + m_RepeatSpacing
Loop
' Shift the starting position (if it's
' run time).
If Not Ambient.UserMode Then Exit Sub
X = X + m_XChange
If m_XChange > 0 Then
If X > 0 Then _
X = -CaptionWidth - m_RepeatSpacing
Else
If X < -CaptionWidth Then _
X = m_RepeatSpacing
End If
End Sub
Private Sub SizeControl()
Static resizing As Boolean
' Do nothing if the caption is blank.
CaptionWidth = TextWidth(m_Caption)
If CaptionWidth <= 0 Then Exit Sub
' Do nothing unless AutoSize is True.
If Not m_AutoSize Then Exit Sub
' Do not recurse.
If resizing Then Exit Sub
resizing = True
Size ScaleX(TextWidth(m_Caption) - ScaleWidth, vbPixels, vbTwips) + Width, _
ScaleY(TextHeight(m_Caption) - ScaleHeight, vbPixels, vbTwips) + Height
resizing = False
DrawText ' Redraw.
End Sub
Private Sub tmrTicker_Timer()
DrawText
End Sub
Private Sub UserControl_Click()
RaiseEvent Click
End Sub
Private Sub UserControl_DblClick()
RaiseEvent DblClick
End Sub
'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES!
'MappingInfo=UserControl,UserControl,-1,Font
Public Property Get Font() As Font
Set Font = UserControl.Font
End Property
Public Property Set Font(ByVal New_Font As Font)
Set UserControl.Font = New_Font
PropertyChanged "Font"
SizeControl ' Resize if necessary.
DrawText ' Redraw.
End Property
Public Property Get Enabled() As Boolean
Enabled = m_Enabled
End Property
Public Property Let Enabled(ByVal New_Enabled As Boolean)
m_Enabled = New_Enabled
PropertyChanged "Enabled"
' Enable or disable if it's run time.
If Ambient.UserMode Then _
tmrTicker.Enabled() = New_Enabled
End Property
'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES!
'MappingInfo=UserControl,UserControl,-1,ForeColor
Public Property Get ForeColor() As OLE_COLOR
ForeColor = UserControl.ForeColor
End Property
Public Property Let ForeColor(ByVal New_ForeColor As OLE_COLOR)
UserControl.ForeColor() = New_ForeColor
PropertyChanged "ForeColor"
DrawText ' Redraw.
End Property
'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES!
'MappingInfo=tmrTicker,tmrTicker,-1,Interval
Public Property Get Interval() As Long
Interval = tmrTicker.Interval
End Property
Public Property Let Interval(ByVal New_Interval As Long)
tmrTicker.Interval() = New_Interval
PropertyChanged "Interval"
End Property
'Initialize Properties for User Control
Private Sub UserControl_InitProperties()
skip_redraw = True
m_AutoSize = m_def_AutoSize
m_Caption = m_def_Caption
Set Font = Ambient.Font
m_RepeatSpacing = m_def_RepeatSpacing
m_XChange = m_def_XChange
skip_redraw = False
If Ambient.UserMode Then tmrTicker.Enabled = m_Enabled
SizeControl ' Resize if necessary.
DrawText ' Redraw.
End Sub
Private Sub UserControl_Paint()
DrawText
End Sub
'Load property values from storage
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
skip_redraw = True
m_AutoSize = PropBag.ReadProperty("AutoSize", m_def_AutoSize)
UserControl.BackColor = PropBag.ReadProperty("BackColor", &H8000000F)
UserControl.BorderStyle = PropBag.ReadProperty("BorderStyle", 0)
m_Caption = PropBag.ReadProperty("Caption", m_def_Caption)
Set Font = PropBag.ReadProperty("Font", Ambient.Font)
m_Enabled = PropBag.ReadProperty("Enabled", m_def_Enabled)
UserControl.ForeColor = PropBag.ReadProperty("ForeColor", &H80000012)
tmrTicker.Interval = PropBag.ReadProperty("Interval", 0)
m_RepeatSpacing = PropBag.ReadProperty("RepeatSpacing", m_def_RepeatSpacing)
m_XChange = PropBag.ReadProperty("XChange", m_def_XChange)
skip_redraw = False
If Ambient.UserMode Then tmrTicker.Enabled = m_Enabled
SizeControl ' Resize if necessary.
DrawText ' Redraw.
End Sub
Private Sub UserControl_Resize()
SizeControl ' Resize if necessary.
End Sub
'Write property values to storage
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
Call PropBag.WriteProperty("AutoSize", m_AutoSize, m_def_AutoSize)
Call PropBag.WriteProperty("BackColor", UserControl.BackColor, &H8000000F)
Call PropBag.WriteProperty("BorderStyle", UserControl.BorderStyle, 0)
Call PropBag.WriteProperty("Caption", m_Caption, m_def_Caption)
Call PropBag.WriteProperty("Font", Font, Ambient.Font)
Call PropBag.WriteProperty("Enabled", m_Enabled, m_def_Enabled)
Call PropBag.WriteProperty("ForeColor", UserControl.ForeColor, &H80000012)
Call PropBag.WriteProperty("Interval", tmrTicker.Interval, 0)
Call PropBag.WriteProperty("RepeatSpacing", m_RepeatSpacing, m_def_RepeatSpacing)
Call PropBag.WriteProperty("XChange", m_XChange, m_def_XChange)
End Sub
Public Property Get RepeatSpacing() As Integer
RepeatSpacing = m_RepeatSpacing
End Property
Public Property Let RepeatSpacing(ByVal New_RepeatSpacing As Integer)
m_RepeatSpacing = New_RepeatSpacing
PropertyChanged "RepeatSpacing"
DrawText ' Redraw.
End Property
Public Property Get XChange() As Integer
XChange = m_XChange
End Property
Public Property Let XChange(ByVal New_XChange As Integer)
m_XChange = New_XChange
PropertyChanged "XChange"
End Property