Tutorial 7: Building a Ticker ActiveX
Control with the ActiveX Control Wizard
by Michael Rounding
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.
if you want to see it work before you do it yourself. We will cover:
• The Control Wizard
• The Code
The Control Wizard
1. Start up VB and start a new ActiveX Control project (as you
see it in Figure 1, below).
Figure 1: new project dialog
2. Set the project name to tickerControl (Figure 2):
1. In the Project Menu, select Project1 Properties
2. Change the Project Name to tickerControl
Figure 2: project properties dialog
3. Set up the layout for the control as pictured below in Figure 3:
1. Add a Timer to the control and call it tmrTicker.
2. Size and position everything like you see it.
3. select the control (your selected object should be
"UserControl1") Change it's name to ctlTicker (this is what it
will be called when you add it to another project.)
4. Start the ActiveX Control Interface Wizard (Figure 4) by:
1. Go to the Project menu
2. Select Add User Control from the menu
3. You'll be presented with a dialog with a few options. One of
the options is VB ActiveX Control Interface Wizard.
Select that.
Figure 4: how to find the illusive VB ActiveX
Control Interface Wizard
5. Skip the introduction screen. The first real screen you see is the
Select Interface Members dialog. You want to have the
following items in your Selected names list. Modify it by movins
stuff from and to the Available names list (check out Figure 5):
BackColor Property
BorderStyle Property
Click Event
DblClick Event
Enabled Property
Font Property
ForeColor Property
Figure 5: select interface members dialog
6. The next dialog you get is the Create Custom Interface
Members dialog. In it, you can add your own properties or
methods that might not come as predefined things in VB. You
want to add the following members (guess what? click the New
button in Figure 6):
AutoSize Property
Caption Property
Interval Property
RepeatSpacing Property
XChange Property
Figure 6: create some custom interface members!
7. In the next dialog, you get to map all of your properties and
events (if you want) to specific controls and member methods /
properties thereof. Below is a list of what you should map for this
ticker control thing:
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
8. After adding your custom interface members, you are presented
with the Set Attributes dialog, which lets you set the attributes
for the members you just added. Fill'em in as follows. Note: you
can fill in the Description field in the attributes of each member
to provide someone using the control with a little bit of feedback
about what that property is for.
Data Default Run Design
Public Name Description
Type Value Time Time
determines whether
the control resizes
AutoSize Boolean 0 R/W R/W
itself to fit the text
displayed
Caption String R/W R/W the text displayed
determines whether
Enabled Boolean 0 R/W R/W the control is enabled
to scroll text
RepeatSpacing Integer 0 R/W R/W the distance in pixels
between occurrences
of the repeating
caption
the distance by which
the text is moved
XChange Integer 0 R/W R/W
when the interval
expires
Figure 8: Set the attributes for the members of your
control
9. Hey, we are done! When you hit the finished button, it'll give you
a report and give you an option to save that summary report to
a file. It may come in handy as a reference, so save it to
wherever you're saving the ActiveX project to. Next up: Code!
Figure 9: and we are done.
The Code
Okay, the complete code is spat out here. Here's how to read it:
• Code generated by VB will appear as greyed out.
• Code that you need to add will appear as normal bolded VB
code. Rock on!
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