You are on page 1of 13

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