Library sample chapters

ActiveX controls

Property Pages

Just browsing the code produced by the wizard is sufficient to understand how property pages work. The PropertyPage object is similar to a form and supports many of the Form object's properties, methods, and events, including Caption, Font, and all the keyboard and mouse events. You might even implement property pages that work as drag-and-drop servers or clients if you need to.

Property pages have their peculiarities, of course. For one, you can control the size of the page using the StandardSize property, which can be assigned one of the values 0-Custom (the size is determined by the object), 1-Small (101-by-375 pixels), or 2-Large (179-by-375 pixels). Microsoft suggests that you create custom-sized pages that aren't larger than the space that you actually need because values other than 0-Custom might display incorrectly at different screen resolutions.

You might notice in Figure 17-15 that the property page doesn't include the OK, Cancel, and Apply buttons that you usually find on standard property pages. Those buttons, in fact, are provided by the environment, and you don't have to add them yourself. The communication between the property page and the environment occurs through properties and events of the PropertyPage object. If the project is associated with a help file, a Help button is also displayed.

When the page loads, the PropertyPage object receives the SelectionChanged event. In this event, your code should load all the controls in the page with the current values of the corresponding properties. The SelectedControls collection returns a reference to all the controls in the form that are currently selected and that will be affected by the property page. For example, this is the code in the SelectionChanged event procedure for the General page of the SuperListBox control:

Private Sub PropertyPage_SelectionChanged()
    txtCaption.Text = SelectedControls(0).Caption
    txtAllItems.Text = SelectedControls(0).AllItems
    chkEnabled.Value = (SelectedControls(0).Enabled And vbChecked)
    cboShowPopupMenu.ListIndex = SelectedControls(0).ShowPopupMenu
    cboBoundPropertyName.Text = SelectedControls(0).BoundPropertyName
    Changed = False
End Sub

When the contents of any field on the page is modified, the code in its Change or Click event should set the PropertyPage's Changed property to True, as in these examples:

Private Sub txtCaption_Change()
    Changed = True
End Sub

Private Sub cboShowPopupMenu_Click()
    Changed = True
End Sub

Setting the Change property to True automatically enables the Apply button. When the user clicks on this button (or simply switches to another property page), the PropertyPage object receives an ApplyChanges event. In this event, you must assign the values on the property page to the corresponding ActiveX control's properties, as in the following example:

Private Sub PropertyPage_ApplyChanges()
    SelectedControls(0).Caption = txtCaption.Text
    SelectedControls(0).AllItems = txtAllItems.Text
    SelectedControls(0).Enabled = chkEnabled.Value
    SelectedControls(0).ShowPopupMenu = cboShowPopupMenu.ListIndex
    SelectedControls(0).BoundPropertyName = cboBoundPropertyName.Text
End Sub

One more custom event is associated with PropertyPage objects-the EditProperties event. This event fires when the property page is displayed because the developer clicked on the ellipsis button beside a property name in the Properties window. (This button appears if the property has been associated with a specific property page in the Procedure Attributes dialog box.) You usually take advantage of this property to automatically move the focus on the corresponding control on the property page:

Private Sub PropertyPage_EditProperty(PropertyName As String)
    Select Case PropertyName
        Case "Caption"
            txtCaption.SetFocus
        Case "AllItems"
            txtAllItems.SetFocus
        ' etc. (other properties omitted...)
    End Select
End Sub

You might also want to disable or hide all other controls on the page, but this is rarely necessary or useful.

Working with multiple selections

The code produced by the Property Page Wizard accounts for only the simplest situation-that is, when only one ActiveX control is selected on the form. To build robust and versatile property pages, you should make them work also with multiple controls. Keep in mind that property pages aren't modal, and therefore the developer is allowed to select (or deselect) controls on the form even when the page is already visible. Each time a new control is added to or removed from the SelectedControls collection, a SelectionChanged event fires.

The standard way to deal with multiple selections is as follows. If the selected controls on the form share the same value for a given property, you fill the corresponding field on the property page with that common value; otherwise, you leave the field blank. This is a modified version of the SelectionChanged that accounts for multiple selections:

Private Sub PropertyPage_SelectionChanged()
    Dim i As Integer
    ' Use the property of the first selected control.
    txtCaption.Text = SelectedControls(0).Caption
    ' If there are other controls, and their Caption property differs from
    ' the Caption of the first selected control, clear the field and exit.
    For i = 1 To SelectedControls.Count - 1
        If SelectedControls(i).Caption <> txtCaption.Text Then
            txtCaption.Text = ""
            Exit For
        End If
    Next

    ' The AllItems property is dealt with in the same way (omitted ...).
    
    ' The Enabled property uses a CheckBox control. If values differ, use
    ' the special vbGrayed setting. 
    chkEnabled.Value = (SelectedControls(0).Enabled And vbChecked)
    For i = 1 To SelectedControls.Count - 1
        If (SelectedControls(i).Enabled And vbChecked) <> chkEnabled.Value 
            Then
            chkEnabled.Value = vbGrayed
            Exit For
        End If
    Next

    ' The ShowPopupMenu enumerated property uses a ComboBox control.
    ' If values differ, set the ComboBox's ListIndex property to _1.
    cboShowPopupMenu.ListIndex = SelectedControls(0).ShowPopupMenu
    For i = 1 To SelectedControls.Count - 1
        If SelectedControls(i).ShowPopupMenu <> cboShowPopupMenu.ListIndex 
            Then
            cboShowPopupMenu.ListIndex = -1
            Exit For
        End If
    Next

    ' The BoundPropertyName property is dealt with similarly (omitted ...).

    Changed = False
    txtCaption.DataChanged = False
    txtAllItems.DataChanged = False
End Sub

The DataChange properties of the two TextBox controls are set to False because in the ApplyChange event you must determine whether the developer entered a value in either of those fields:

Private Sub PropertyPage_ApplyChanges()
    Dim ctrl As Object
    ' Apply changes to Caption property only if the field was modified.
    If txtCaption.DataChanged Then
        For Each ctrl In SelectedControls
            ctrl.Caption = txtCaption.Text
        Next
    End If
    ' The AllItems property is deal with in the same way (omitted ...).
    
    ' Apply changes to the Enabled property only if the CheckBox control
    ' isn't grayed out.
    If chkEnabled.Value <> vbGrayed Then
        For Each ctrl In SelectedControls
            ctrl.Enabled = chkEnabled.Value
        Next
    End If

    ' Apply changes to the ShowPopupMenu property only if an item 
    ' in the ComboBox control is selected.
    If cboShowPopupMenu.ListIndex <> -1 Then
        For Each ctrl In SelectedControls
            ctrl.ShowPopupMenu = cboShowPopupMenu.ListIndex
        Next
    End If
    ' The BoundPropertyName property is dealt with similarly (omitted ...).
End Sub

Advanced techniques

I want to mention a few techniques that you can use with property pages and that aren't immediately obvious. For example, you don't need to wait for the ApplyChanges event to modify a property in selected ActiveX controls: You can update a property right in the Change or Click event of the corresponding control on the property page. You can therefore achieve in the property page the same behavior that you can implement in the Properties window by assigning a property the Text or Caption procedure ID.

Another easy-to-overlook feature is that the PropertyPage object can invoke Friend properties and methods of the UserControl module because they're in the same project. This gives you some additional flexibility: For example, the UserControl module can expose one of its constituent controls as a Friend Property Get procedure so that the Property Page can directly manipulate its attributes, as you can see in the code at below.

' In the SuperListBox UserControl module
Friend Property Get Ctrl_List1() As ListBox
    Set Ctrl_List1 = List1
End Property

A minor annoyance of this approach is that the PropertyPage code accesses the UserControl through the SelectedControls collection, which returns a generic Object, whereas Friend members can only be accessed through specific object variables. You can work around this issue by casting the elements of the collection to specific object variables:

' In the PropertyPage module
Dim ctrl As SuperListBox
' Cast the generic control to a specific SuperListBox variable.
Set ctrl = SelectedControls(0)
' Now it is possible to access Friend members.
ctrl.Ctrl_List1.AddItem "New Item"

The last technique that I'm showing you is likely to be useful when you're developing complex UserControls with many properties and constituent controls, such as the Customer ActiveX control that I introduced earlier in this chapter. Surprisingly, it turns out that you can use the UserControl even on a property page that's associated with itself. Figure 17-16 shows an example of this technique: The General property page uses an instance of the Customer ActiveX control to let the developer assign the properties of the Customer control itself!


Figure 17-16.
A property page that uses an instance of the UserControl object defined in its own project.

The beauty of this approach is how little code you need to write in the PropertyPage module. This is the complete source code of the property page shown in Figure 17-16:

Private Sub Customer1_Change(PropertyName As String)
    Changed = True
End Sub

Private Sub PropertyPage_ApplyChanges()
    ' Read all properties in one loop.
    Dim propname As Variant
    For Each propname In Array("CustomerName", "Address", "City", _
        "ZipCode", "Country", "Phone", "Fax")
        CallByName SelectedControls(0), propname, VbLet, _
            CallByName(Customer1, propname, VbGet)
    Next
End Sub

Private Sub PropertyPage_SelectionChanged()
    ' Assign all properties in one loop.
    Dim propname As Variant
    For Each propname In Array("CustomerName", "Address", "City", _
        "ZipCode", "Country", "Phone", "Fax")
        CallByName Customer1, propname, VbLet, _
            CallByName(SelectedControls(0), propname, VbGet)
    Next
End Sub

Notice how the code takes advantage of the CallByName function to streamline multiple assignments to and from the properties in the UserControl.

Comments

  1. 21 Jul 2006 at 10:33

    I also looking for the control for years, but still can't get a good one, some control only make a form transparent instead of a control like picturebox, some control only copy the picture of  background under it, isn't real transparent. some controls have transparent background but the transparent area is  a hole that you can click controls behind it in z-order. I ever tried the following code in a form:

    Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
    Global Const GWL_EXSTYLE = (-20)
    Global Const WS_EX_TRANSPARENT = &H20&

    add a textbox on the form and a picturebox named picturebox1 over it, in form_load event add this code:
        SetWindowLong picturebox1.hwnd, GWL_EXSTYLE, WS_EX_TRANSPARENT


    the problems are, only when content of textbox change(by code), the picturebox was changed to transparent, second, when then picturebox resized, the picturebox was changed back to white.usually.

    dear sir, if you have got a ideal method to make this control, would you please send me a copy? thank a lot.

  2. 21 Jul 2005 at 00:24

    i want to create a transperent picturebox behind it i will put internet control / webbrowser.
    user will able to see the webpage and unable to click  on web page ,
    and he would not be able to select text / image .


      is it possible to create such a activx picture box . i need it  urgently .  please reply.as  soon as  possible

  3. 28 Apr 2005 at 17:13

    In .NET it is possible to show properties to users of comoponents during runtime.  Is there a method to show PropertyPages during Runtime of a VB 6.0 ActiveX control?


    Thanks

  4. 28 Apr 2005 at 17:12

    In .NET it is possible to show properties to users of comoponents during runtime.  Is there a method to show PropertyPages during Runtime of a VB 6.0 ActiveX control?


    Thanks

  5. 27 Apr 2005 at 16:14

    Does anyone know how can I convert a *.vbp (visual basic project) into an activex control to use it on a Web Page?

  6. 12 Mar 2005 at 02:46

    Is it possible to digitally sign an already packaged Active X control or does the code have to be signed.
    I want to sign MsRdpClient so we can use it on our intranet without changing IE security settings in the GPO.
    Thanks

  7. 18 Mar 2004 at 04:59

    Hi
    very thanx from givig imediate reply.
    I have a property page for ActiveX control & if i right click on that control in client design view its show popup menu & in that option is property after clicking it shows the property page what ever i made But the same proprprty page I wan tto display at run time . cos i m developing active control like Rational Rose. so that user ca draw the flow digram & at that time (run time) user can be able to change the property at run time its Background , style etc so it is possible to show the property page at run time
    Plz comments


    Thanx
    Regards
    Mahesh

  8. 18 Mar 2004 at 01:03

    Hi


    I want to show the property page at run time for a activeX control so that user can change the backgroun color & style of drawing .
    any buddy knows how to show ?
    plz comment


    Thanx
    Regards

  9. 17 Nov 2003 at 06:24

    adadf

  10. 17 Oct 2003 at 22:40

    Deep and clear. It was just I was looking for. Great! Thank you.

  11. 01 Jan 1999 at 00:00

    This thread is for discussions of ActiveX controls.

Leave a comment

Sign in or Join us (it's free).

Want to stay in touch with what's going on? Follow us on twitter!