Jalaj

January 11, 2007

Creating Custom ActiveX Controls - 3

Filed under: COM, Visual Basic — Jalaj @ 10:57 am

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

http://jalaj.files.wordpress.com/2007/01/control2.jpg

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

Blog at WordPress.com.