Dear John, How Do I... Create a Design-Time Property?

The TargetObject and Interval properties of the Blinker control can be set at runtime. To create a property that can be set from the Properties window at design time, you need to use the PropertyBag object in the ReadProperties and WriteProperties events, as shown below:

`Make Interval a design-time property
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
    updnRate.Value = PropBag.ReadProperty("Interval", 0)
End Sub

Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
    PropBag.WriteProperty "Interval", updnRate.Value, 0
End Sub

This code adds the Interval property to the Blinker control's list of properties in the Visual Basic Properties window, as shown in Figure 6-6.

Click to view at full size.

Figure 6-6. The PropertyBag object being used to add properties to the Properties window.

You need to add a PropertyChanged statement to the control's Interval Property Let procedure so that Visual Basic will save changes to the property at design time. The following code shows the modified procedure:

`~~~.Interval
Public Property Let Interval(Setting As Integer)
    `Set UpDown control--updates TextBox and
    `Timer controls as well
    updnRate.Value = Setting
    `Update design-time setting
    PropertyChanged "Interval"
End Property

Finally, you need to ensure that design-time changes to the Interval property don't trigger the Timer event. You can tell whether a control is in design mode or user mode by checking the UserControl object's Ambient.UserMode property. UserMode is False during design time and True at runtime. The following changes to the TextBox's Change event procedure prevents errors from occurring at design time when Interval is set to a nonzero value:

Private Sub txtRate_Change()
    `Exit if in design mode
    If Not UserControl.Ambient.UserMode Then Exit Sub
    `Set Timer control's Interval property
    `to match value in text box
    If txtRate = 0 Then
        tmrBlink.Interval = 0
        tmrBlink.Enabled = False
        mblnInitialized = False
        `If blinking is turned off, be sure object 
        `is returned to its original state
        If TypeOf mobjTarget Is Form Then
            FlashWindow mobjTarget.hwnd, CLng(False)
        ElseIf TypeOf mobjTarget Is Control Then
            mobjTarget.ForeColor = mlngForeground
            mobjTarget.BackColor = mlngBackground
        End If
    Else
        tmrBlink.Enabled = True
        tmrBlink.Interval = 1000 \ txtRate
    End If
End Sub

NOTE

The UserMode property is not available within the control's Initialize event.

Making the TargetObject property available at design time is tricky. Since Visual Basic Properties windows can't display objects, you need to create a new property that accepts a string that, in turn, sets the TargetObject property. The TargetString property shown here can appear in the Properties window:

`~~~.TargetString
Public Property Let TargetString(Setting As String)
    If UserControl.Parent.Name = Setting Then
        Set TargetObject = UserControl.Parent
    ElseIf Setting <> "" Then
        Set TargetObject = UserControl.Parent.Controls(Setting)
    End If
End Property

Public Property Get TargetString() As String
    If TypeName(mobjTarget) <> "Nothing" Then
        TargetString = mobjTarget.Name
    Else
        TargetString = ""
    End If
End Property

You also need to add a PropertyChanged statement to the control's TargetObject property, as shown in the following code:

`~~~.TargetObject
Public Property Set TargetObject(Setting As Object)
    If TypeName(Setting) = "Nothing" Then Exit Property
    `Set internal object variable
    Set mobjTarget = Setting
    `Property has changed
    PropertyChanged "TargetObject"
End Property

To add the TargetString property to the Properties window, edit the control's ReadProperties and WriteProperties event procedures as follows:

`Get design-time settings
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
    updnRate.Value = PropBag.ReadProperty("Interval", 0)
    TargetString = PropBag.ReadProperty("TargetString", "")
End Sub

`Save design-time settings
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
    PropBag.WriteProperty "Interval", updnRate.Value, 0
    PropBag.WriteProperty "TargetString", TargetString, ""
End Sub