Creating Custom ActiveX Controls - 3
The Control that we created in previous post Creating Custom ActiveX Controls - 2 were though functional but lacked some essential features. Whatever the the size of the control on form the textBox and the button remained static, giving you not option to change sizes. The Text on the Button and the font used could not be changed.
Lets go ahead adding properties ButtonWidth, ButtonText and Font, starting with the private variables of type Long, String and StdFont. StdFont is a class defined in the StdOLE library (referenced in a project by default) which holds all properties related to font (Bold, Charset, Italic, Name, Size, Strikethrough, Underline, Weight)
Dim m_ButtonWidth As Long Dim m_ButtonText As String Dim m_Font As New StdFont
Add followgin lines to InitProperties event of the UserControl. The Ambient object exposes a few properties of the Parent Form. We will use the Ambient.Font as the default Font setting for the control. RefreshControl is a subroutine which we will be calling whenever a change to Control’s property has visual impact on it.
m_ButtonText = "Browse..."
m_ButtonWidth = 1000
Set m_Font = Ambient.Font
Call RefreshControl
Add following lines to the WriteProperties event of UserControl. Note that instead of writing a single property “Font” all the member properties of the StdFont class will be required to be written.
Call PropBag.WriteProperty("ButtonWidth", m_ButtonWidth, 1000)
Call PropBag.WriteProperty("ButtonText", m_ButtonText, "Browse...")
Call PropBag.WriteProperty("Font", m_Font.Name, Ambient.Font.Name)
Call PropBag.WriteProperty("Bold", m_Font.Bold, Ambient.Font.Bold)
Call PropBag.WriteProperty("Charset", m_Font.Charset, Ambient.Font.Charset)
Call PropBag.WriteProperty("Italic", m_Font.Italic, Ambient.Font.Italic)
Call PropBag.WriteProperty("Size", m_Font.Size, Ambient.Font.Size)
Call PropBag.WriteProperty("Strikethrough", m_Font.Strikethrough, Ambient.Font.Strikethrough)
Call PropBag.WriteProperty("Underline", m_Font.Underline, Ambient.Font.Underline)
Call PropBag.WriteProperty("Weight", m_Font.Weight, Ambient.Font.Weight)
Similarly add following lines to ReadProperties event of the usercontrol.
m_ButtonWidth = PropBag.ReadProperty("ButtonWidth", 1000)
m_ButtonText = PropBag.ReadProperty("ButtonText", "Browse...")
m_Font.Name = PropBag.ReadProperty("Font", Ambient.Font.Name)
m_Font.Bold = PropBag.ReadProperty("Bold", Ambient.Font.Bold)
m_Font.Charset = PropBag.ReadProperty("Charset", Ambient.Font.Charset)
m_Font.Italic = PropBag.ReadProperty("Italic", Ambient.Font.Italic)
m_Font.Size = PropBag.ReadProperty("Size", Ambient.Font.Size)
m_Font.Strikethrough = PropBag.ReadProperty("Strikethrough", Ambient.Font.Strikethrough)
m_Font.Underline = PropBag.ReadProperty("Underline", Ambient.Font.Underline)
m_Font.Weight = PropBag.ReadProperty("Weight", Ambient.Font.Weight)
Now add the code for handling the read / write to the ButtonWidth, ButtonText and Font properties
Public Property Let ButtonWidth(ByVal lngButtonWidth As Long)
m_ButtonWidth = lngButtonWidth
PropertyChanged "ButtonWidth"
Call RefreshControl
End Property
Public Property Get ButtonWidth() As Long
ButtonWidth = m_ButtonWidth
End Property
Public Property Let ButtonText(ByVal strButtonText As String)
m_ButtonText = strButtonText
PropertyChanged "ButtonText"
Call RefreshControl
End Property
Public Property Get ButtonText() As String
ButtonText = m_ButtonText
End Property
Public Property Set Font(ByVal objFFont As StdFont)
Set m_Font = objFFont
PropertyChanged "Font"
Call RefreshControl
End Property
Public Property Get Font() As StdFont
Set Font = m_Font
End Property
Now the RefreshControl subroutine which we have been calling on Initialisation & Changes of properties. This subroutine ensures that whatever be the size of the control on the parent form, the position and sizes of the textBox and command button are adjusted accordingly. An allowance of 25 units can be seen in the codes as the 3D appearance of the lower ends and right side of the controls sometimes gets truncated. If the Width of the control is less than the ButtonWidth property the button is adjusted to the lower value.
The textBox increases and decreases in width with the change in width of Control (We have only defined the ButtonWidth property) and disappears when the size of the control is very low to accomodate it. There is always a fixed gap between it and the button.
Private Sub RefreshControl()
With cmdOpen
If m_ButtonWidth > (UserControl.Width - 25) Then
.Width = UserControl.Width - 25
Else
.Width = m_ButtonWidth
End If
.Top = 0
.Left = UserControl.Width - cmdOpen.Width - 25
.Height = UserControl.Height - 25
.Top = 0
.Caption = m_ButtonText
End With
With txtFileName
.Top = 0
.Left = 0
.Height = UserControl.Height - 25
If (UserControl.Width - cmdOpen.Width - 100) < 0 Then
.Width = 0
.Visible = False
Else
.Width = UserControl.Width - cmdOpen.Width - 100
.Visible = True
End If
End With
Set cmdOpen.Font = m_Font
Set txtFileName.Font = m_Font
End Sub
Now finally the Resize event of the Usercontrol, which will ensure that the RefreshControl subroutine is called whenever the control is resized.
Private Sub UserControl_Resize()
Call RefreshControl
End Sub

This process of creating each property can be simplified using the “ActiveX Control User Interface wizard” available as add-in to Visual Basic.
Below is the Complete Code including the one from earlier posts.
Dim m_FileName As String
Dim m_DialogType As Integer
Dim m_DefaultExt As String
Dim m_DialogTitle As String
Dim m_Filter As String
Dim m_ButtonWidth As Long
Dim m_ButtonText As String
Dim m_Font As New StdFont
Enum PropDialogType
[File Open Dialog] = 1
[File Save Dialog] = 2
End Enum
Public Property Let ButtonWidth(ByVal lngButtonWidth As Long)
m_ButtonWidth = lngButtonWidth
PropertyChanged “ButtonWidth”
Call RefreshControl
End Property
Public Property Get ButtonWidth() As Long
ButtonWidth = m_ButtonWidth
End Property
Public Property Let ButtonText(ByVal strButtonText As String)
m_ButtonText = strButtonText
PropertyChanged “ButtonText”
Call RefreshControl
End Property
Public Property Get ButtonText() As String
ButtonText = m_ButtonText
End Property
Public Property Set Font(ByVal objFFont As StdFont)
Set m_Font = objFFont
PropertyChanged “Font”
Call RefreshControl
End Property
Public Property Get Font() As StdFont
Set Font = m_Font
End Property
Public Property Let FileName(ByVal strFileName As String)
txtFileName = strFileName
m_FileName = strFileName
PropertyChanged “FileName”
End Property
Public Property Get FileName() As String
FileName = m_FileName
End Property
Public Property Let DialogType(ByVal intDialog As PropDialogType)
m_DialogType = intDialog
PropertyChanged “DialogType”
End Property
Public Property Get DialogType() As PropDialogType
DialogType = m_DialogType
End Property
Public Property Let DefaultExt(ByVal strDefaultExt As String)
m_DefaultExt = strDefaultExt
PropertyChanged “DefaultExt”
End Property
Public Property Get DefaultExt() As String
DefaultExt = m_DefaultExt
End Property
Public Property Let DialogTitle(ByVal strDialogTitle As String)
m_DialogTitle = strDialogTitle
PropertyChanged “DialogTitle”
End Property
Public Property Get DialogTitle() As String
DialogTitle = m_DialogTitle
End Property
Public Property Let Filter(ByVal strFilter As String)
m_Filter = strFilter
PropertyChanged “Filter”
End Property
Public Property Get Filter() As String
Filter = m_Filter
End Property
Private Sub cmdOpen_Click()
dlgOpen.DefaultExt = m_DefaultExt
dlgOpen.DialogTitle = m_DialogTitle
dlgOpen.Filter = m_Filter
If m_DialogType = 1 Then
dlgOpen.ShowOpen
Else
dlgOpen.ShowSave
End If
If dlgOpen.FileName “” Then
txtFileName = dlgOpen.FileName
End If
End Sub
Private Sub txtFileName_Change()
m_FileName = txtFileName
End Sub
Private Sub UserControl_InitProperties()
m_DialogType = 1
m_ButtonText = “Browse…”
m_ButtonWidth = 1000
Set m_Font = Ambient.Font
Call RefreshControl
End Sub
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
Call PropBag.WriteProperty(”FileName”, m_FileName, “”)
Call PropBag.WriteProperty(”DialogType”, m_DialogType, 1)
Call PropBag.WriteProperty(”DefaultExt”, m_DefaultExt, “”)
Call PropBag.WriteProperty(”DialogTitle”, m_DialogTitle, “”)
Call PropBag.WriteProperty(”Filter”, m_Filter, “”)
Call PropBag.WriteProperty(”ButtonWidth”, m_ButtonWidth, 1000)
Call PropBag.WriteProperty(”ButtonText”, m_ButtonText, “Browse…”)
Call PropBag.WriteProperty(”Font”, m_Font.Name, Ambient.Font.Name)
Call PropBag.WriteProperty(”Bold”, m_Font.Bold, Ambient.Font.Bold)
Call PropBag.WriteProperty(”Charset”, m_Font.Charset, Ambient.Font.Charset)
Call PropBag.WriteProperty(”Italic”, m_Font.Italic, Ambient.Font.Italic)
Call PropBag.WriteProperty(”Size”, m_Font.Size, Ambient.Font.Size)
Call PropBag.WriteProperty(”Strikethrough”, m_Font.Strikethrough, Ambient.Font.Strikethrough)
Call PropBag.WriteProperty(”Underline”, m_Font.Underline, Ambient.Font.Underline)
Call PropBag.WriteProperty(”Weight”, m_Font.Weight, Ambient.Font.Weight)
End Sub
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
txtFileName = PropBag.ReadProperty(”FileName”, “”)
m_DialogType = PropBag.ReadProperty(”DialogType”, 1)
m_DefaultExt = PropBag.ReadProperty(”DefaultExt”, “”)
m_DialogTitle = PropBag.ReadProperty(”DialogTitle”, “”)
m_Filter = PropBag.ReadProperty(”Filter”, “”)
m_ButtonWidth = PropBag.ReadProperty(”ButtonWidth”, 1000)
m_ButtonText = PropBag.ReadProperty(”ButtonText”, “Browse…”)
m_Font.Name = PropBag.ReadProperty(”Font”, Ambient.Font.Name)
m_Font.Bold = PropBag.ReadProperty(”Bold”, Ambient.Font.Bold)
m_Font.Charset = PropBag.ReadProperty(”Charset”, Ambient.Font.Charset)
m_Font.Italic = PropBag.ReadProperty(”Italic”, Ambient.Font.Italic)
m_Font.Size = PropBag.ReadProperty(”Size”, Ambient.Font.Size)
m_Font.Strikethrough = PropBag.ReadProperty(”Strikethrough”, Ambient.Font.Strikethrough)
m_Font.Underline = PropBag.ReadProperty(”Underline”, Ambient.Font.Underline)
m_Font.Weight = PropBag.ReadProperty(”Weight”, Ambient.Font.Weight)
End Sub
Private Sub RefreshControl()
With cmdOpen
If m_ButtonWidth > (UserControl.Width - 25) Then
.Width = UserControl.Width - 25
Else
.Width = m_ButtonWidth
End If
.Top = 0
.Left = UserControl.Width - cmdOpen.Width - 25
.Height = UserControl.Height - 25
.Top = 0
.Caption = m_ButtonText
End With
With txtFileName
.Top = 0
.Left = 0
.Height = UserControl.Height - 25
If (UserControl.Width - cmdOpen.Width - 100) < 0 Then
.Width = 0
.Visible = False
Else
.Width = UserControl.Width - cmdOpen.Width - 100
.Visible = True
End If
End With
Set cmdOpen.Font = m_Font
Set txtFileName.Font = m_Font
End Sub
Private Sub UserControl_Resize()
Call RefreshControl
End Sub
