Free Web Hosting Provider - Web Hosting - E-commerce - High Speed Internet - Free Web Page
Search the Web

Creating a Color Control

add to favorite Add to Favorites

In this article, you will learn how to initialize and terminate controls and how to use unique properties, methods, and events. To simplify the discussion. We will not use the Wizard but will implement all the properties and methods manually so that you'll get some experience in editing controls.

Creating a Color Control

Let's start by creating a color control. Follow these steps:

  1. Choose File > New Project to open the New Project window.
  2. Click the ActiveX control icon. Visual Basic creates a new project that contains a UserControl, named UserControl1. This is the control's Form on which the visible interface will be built.
  3. Choose File > Add Project to add a standard Exe project. Visual Basic creates a new project with a single Form, name Form1. You'll use Fomr1 to test the control. (Form1 is frequently called the "test Form," and the project it belongs to is called the "test project.") What you have on your screen now is a generic control.
  4. This is a good point at which to rename and save your project's files. For this project, use the default names.
  5. Close the control's design window to enable the control's icon in the toolbox.
  6. Place an instance of the new control on the Form. The newly created Form doesn't' have a background color or a border that will distinguish it from the Form on which it lies.
  7. With the control selected, open the Properties window.
    -
    DragIcon DragMode
    Height HelpContextID
    Index Left
    TabIndex TabStop
    Tag ToolTipText
    Top, Left Visible
    WhaIsThisHelp ID Width

    These properties are actually provided by the container. The left property is determined by the container and has meaning only in the context of a container. Likewise, the TabIndex and TabStop properties aren't managed by the control itself, because the control doesn't know what other controls exist on the Form. Only the Form does, and therefore the Form must maintain these properties for its controls.

    Test a few of these properties. Assign the value "My Color Control" to the ToolTipText property. Run the application, and then rest the pointer for a second over the control. The string you entered is displayed in a ToolTip box. In a similar manner, you can test the Tag property by assigning a string to it, or you can test the Index property by creating multiple instances of the same control on the Form with the same name and a different Index value. There's not a single line of code you should add to the control to implement these properties.

    Adding a Property

        Let's add a property to our Color control. We'll call it Title, and we'll store its value internally to the m_Title private property. Select UserControl1 in the Project window, and in the Code window, insert the following declaration:

        Private m_Title As String

    and then the procedures:

        Public Property Get Title() As String
            Title = m_Title
        End Property

        Public Property Let Title(ByVal vNewTitle As String)
            m_Title = vNewTitle
        End Property


    Close the UserControl design window and the Code window, switch to the test Form, select the new control, and look up its new property in the Properties window. The mere presence of the Let and Get procedures is all that Visual Basic needs to add a property to the control. Enter a new value in the Title property's box (For example: Control Color. As expected, the title won't appear on the control.

    We must also write a few lines of code to display the Title. Switch back to the UserControl window, double-click it to open the Code window, and in the paint event, enter the following:

        Private Sub UserControl_Paint()
            UserControl.CurrentX = 0
            UserControl.CurrentY = 0
            UserControl.Print m_Title
        End Sub

    Tip The first two statements aren't really needed to display something at the control's upper left corner. but you must set them accordingly if you want to display something else where on the control.

    Switch back to the test Form. If you have any other custom control on the Form, delete them.

    Add an instance of the custom control (it will automatically be named UserControl1 unless you have changed the name of the UserControl object), and then assign a value to the Title property. Set the title to My Color Control, for instance. The title won't appear the moment you enter it because the paint event isn't triggered when a property changes values. You must resize the control to force paint event and display the title. If you don't like the font, change the UserControl's font property (our control doesn't have a Font property yet).

    Every time a new property is set, the Property let procedure is invoked. You must, therefore, call the Paint method from within the Property Let procedure so that the title is displayed as soon as it's entered. Switch back to the UserControl, add the following line to the Property Let Title procedure:

        userControl_Paint

    Now assign a value to the Title property and watch the string appear on the control.

    Now, press F5 to run the application. The title won't appear on the control. It was there at design time, but it disappeared at runtime. You probably want to stop the application and look up the value of the Title property to make sure it still contains its value. But you're in for a surprise. The Title property's value is a blank string like before. It wasn't your fault, so don't repeat the process. Any properties set at design time lose their value at runtime. It's a strange behavior, but this how controls work.

    Your experience with Visual Basic tells you that any properties set at design time keep their values at runtime. To make this happen you must first save the property values to Property Bag. What's not so easy to guess is when an action must take place.

    Key Events in a Control's Lifetime

    When you place an instance of a control on the Form, the following events take place:

    Initialize initializes the design-time instance of the control.
    initProperties assigns initial values to the properties.

    When you switch from design time to runtime, the following events take place:

    WriteProperties saves the properties listed in the Properties window.
    Terminate terminates the design-time instance of the control.
    Initialize initializes a new, runtime instance of the control.
    ReadProperties reads the saved properties.

    When you switch from runtime to design time, the following events take place:

    Initialize initializes the design-time instance of the control.
    ReadProperties Reads the values from the Properties window and assigns them to the corresponding properties.

    Tip When you switch from runtime to design-time mode, no WriteProperties event takes place. As expected, Visual Basic doesn't save properties that changed at runtime and resets the ActiveX control to the properties set in the Properties window at design time.

    To maintain the values of the properties when the control switches from design to runtime, you must add a few lines of code in the ReadProperties and WriteProperties events. We have looked at how property values are written to and read from the Property Bag object, so here's the code for the Title property:

        Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
            Title = PropBag.ReadProperty("Title", "Control Title")
        End Sub
       
        Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
            PropBag.WriteProperty "Title", m_Title, "Control Title"
        End Sub

    Initializing the Control and its Properties

    You can use two events to maintain the control - Initialize and initProperties. The ActiveX User Interface Wizard does it so well for us. The initialize event can be used to enter initialization code that doesn't involve properties. If you try to set a property value or do something on the control, you'll get the following error message:

        Object Required

    The UserControl object is being initialized. It doesn't exist yet. That's why UserControl.Print "Control" works when executed form within other events, but not from within the Initialize event.

    So, what can you do from within this event? Not match. You can assign initial values o the private variables of the control, but you can't access the control's properties, not event the Ambient object.

    The event of interest is the initProperties event, which takes place after the control is created. This behavior may strike you as strange: The initialize event takes place every time you switch between design and runtime mode, but the initProperties event doesn't follow.

    In the InitProperties event, you can insert initialization code that controls the appearance of a "newborn" control. For instance, you can determine what happens if the user places the control on a Form by double-click on its icon instead of actually drawing the control on the Form. Visual Basic places an instance of the control on the Form, and it will have a certain size (which is the same for all controls). If your control contains a long default title, a shape, or any element you want to be entirely visible, you can adjust the initial size of the control with a couple of statements such as the following:

        UserControl.Width = 2400
        UserControl.Height = 1200

    When your control is placed on a Form with a double-click of its icon, its initial size is 2400 by 1200 twips.

    The Extender and Ambient objects are also available from within the InitProperties control, because the control has been sited. You can display a title on the control in the same font as the container's font, as follows:

        Set Font = Ambient.Font
        UserControl.PropertyChanged "VBGreatone"

    These two lines display the string "VBGratone" in the control's upper left corner, in the font of the container. In addition, your contro's font will also be initially set to the Form's font.

    A control's Key Properties

        As you have learned, the UserControl object is basically a Form on which you can place other controls, draw shapes, display text, and detect events, It even has properties such as AutoRedraw and ScaleMode, which make it suitable for drawing at runtime. But it's not called Form; it's call UserControl. In addition, it has a few properties that are unique ActiveX controls, and we are going to look at them in this section.

    CanGetFocus Set this property to True if the control can receive the focus, either with the mouse or with the Tab key. A user control can get the focus if the UserControl object gets the focus or if one of its constituent controls can get the focus. If the control can get the Focas, the EnterFocus and ExitFocus events are triggered every time the focus is moved in or out of the control.

    ControlContainer If this property is set to True, the user control can become a container for other controls. Normally, the controls placed on a container are grouped with the container, and they all move together. When you reposition the container control on the Form, all the controls contained in it are moved along.

    By default, a user control is not a container. In other words, it is possible to draw a Command Button that lies half on the user control and half outside. To change this behavior, set the ControlContainer property to True.

    Alignable If the Alignable property is set to True, the user control has an Align property at design time. The Align property determines whether and how the control is aligned on the Form.

    InvisibleAtRuntime some controls, the Timer being the most typical example, are invisible at runtime. If your user control does not have a user interface and need not appear on the Form, set its InvisibleAtRuntime property to True.

    ToolboxBitmap use this property to display a bmp file in the toolbox in place of the ActiveX Control generic icon. The ToolboxBitmap property's value is a BMP file's path name, but the bitmap is stored in the control and distributed with it.

    AccessKeys  You use this property to specify which keys will act as how keys for this control. If you want the user to move the focus instantly to your control by pressing a hot-key combination (Alt+key), assign the key value to the Accesskeys property.

  8. Complete Code for the Color Control:

    Add and place the following controls on the UserControl form like Pic 1:

    Pic 1:
    pic1.bmp (87254 bytes)

    Set The follow properties:

    Paste the following code in to the usercontrol's code:
    'Default Property Values:
    Const m_def_RedComponent = 128
    Const m_def_GreenComponent = 128
    Const m_def_BlueComponent = 128
    Const m_def_SelectedColor = &HFFFF00
    'Property Variables:
    Dim m_RedComponent As Byte
    Dim m_GreenComponent As Byte
    Dim m_BlueComponent As Byte
    Dim m_SelectedColor As OLE_COLOR
    ' Events
    Event RedChanged()
    Event GreenChanged()
    Event BlueChanged()

    Private Sub Component_Change(Index As Integer)
        UpdateColors Index
        UpdateValues
    End Sub

    Private Sub Component_Scroll(Index As Integer)
        UpdateColors Index
        UpdateValues
    End Sub

    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"
    End Property

    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"
    End Property

    Public Property Get Enabled() As Boolean
        Enabled = UserControl.Enabled
    End Property

    Public Property Let Enabled(ByVal New_Enabled As Boolean)
        UserControl.Enabled() = New_Enabled
        PropertyChanged "Enabled"
    End Property

    Public Property Get BackStyle() As Integer
        BackStyle = UserControl.BackStyle
    End Property

    Public Property Let BackStyle(ByVal New_BackStyle As Integer)
        UserControl.BackStyle() = New_BackStyle
        PropertyChanged "BackStyle"
    End Property

    Public Property Get BorderStyle() As Integer
        BorderStyle = UserControl.BorderStyle
    End Property

    Public Property Let BorderStyle(ByVal New_BorderStyle As Integer)
        UserControl.BorderStyle() = New_BorderStyle
        PropertyChanged "BorderStyle"
    End Property

    Public Sub Refresh()
        UserControl.Refresh
    End Sub

    Public Property Get SelectedColor() As OLE_COLOR
        SelectedColor = m_SelectedColor
    End Property

    Public Property Let SelectedColor(ByVal New_SelectedColor As OLE_COLOR)
        m_SelectedColor = New_SelectedColor
        Picture1.BackColor = m_SelectedColor
        m_RedComponent = SelectedColor And &HFF
        m_GreenComponent = (SelectedColor / 256) And &HFF
        m_BlueComponent = (SelectedColor / (256 ^ 2)) And &HFF
        UpdateScrollbars
        PropertyChanged "RedComponent"
        PropertyChanged "GreenComponent"
        PropertyChanged "BlueComponent"
        PropertyChanged "SelectedColor"
    End Property

    'Initialize Properties for User Control
    Private Sub UserControl_InitProperties()
        m_SelectedColor = m_def_SelectedColor
        m_RedComponent = m_def_RedComponent
        m_GreenComponent = m_def_GreenComponent
        m_BlueComponent = m_def_BlueComponent
    End Sub

    'Load property values from storage
    Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
        UserControl.BackColor = PropBag.ReadProperty("BackColor", &H8000000F)
        UserControl.ForeColor = PropBag.ReadProperty("ForeColor", &H80000012)
        UserControl.Enabled = PropBag.ReadProperty("Enabled", True)
        UserControl.BackStyle = PropBag.ReadProperty("BackStyle", 1)
        UserControl.BorderStyle = PropBag.ReadProperty("BorderStyle", 0)
        m_SelectedColor = PropBag.ReadProperty("SelectedColor", m_def_SelectedColor)
        m_RedComponent = PropBag.ReadProperty("RedComponent", m_def_RedComponent)
        m_GreenComponent = PropBag.ReadProperty("GreenComponent", m_def_GreenComponent)
        m_BlueComponent = PropBag.ReadProperty("BlueComponent", m_def_BlueComponent)
        UpdateScrollbars
    End Sub

    Private Sub UserControl_Resize()
        UserControl.Width = Component(0).Left + Component(0).Width + 2 * Picture1.Left
        UserControl.Height = Picture1.Width + 3 * Picture1.Top
    End Sub


    'Write property values to storage
    Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
        Call PropBag.WriteProperty("BackColor", UserControl.BackColor, &H8000000F)
        Call PropBag.WriteProperty("ForeColor", UserControl.ForeColor, &H80000012)
        Call PropBag.WriteProperty("Enabled", UserControl.Enabled, True)
        Call PropBag.WriteProperty("BackStyle", UserControl.BackStyle, 1)
        Call PropBag.WriteProperty("BorderStyle", UserControl.BorderStyle, 0)
        Call PropBag.WriteProperty("SelectedColor", m_SelectedColor, m_def_SelectedColor)
        Call PropBag.WriteProperty("RedComponent", m_RedComponent, m_def_RedComponent)
        Call PropBag.WriteProperty("GreenComponent", m_GreenComponent, m_def_GreenComponent)
        Call PropBag.WriteProperty("BlueComponent", m_BlueComponent, m_def_BlueComponent)
    End Sub

    Public Property Get RedComponent() As Byte
        RedComponent = m_RedComponent
    End Property

    Public Property Let RedComponent(ByVal New_RedComponent As Byte)
        m_RedComponent = New_RedComponent
        UpdateScrollbars
        PropertyChanged "RedComponent"
    End Property

    Public Property Get GreenComponent() As Byte
        GreenComponent = m_GreenComponent
    End Property

    Public Property Let GreenComponent(ByVal New_GreenComponent As Byte)
        m_GreenComponent = New_GreenComponent
        UpdateScrollbars
        PropertyChanged "GreenComponent"
    End Property

    Public Property Get BlueComponent() As Byte
        BlueComponent = m_BlueComponent
    End Property

    Public Property Let BlueComponent(ByVal New_BlueComponent As Byte)
        m_BlueComponent = New_BlueComponent
        UpdateScrollbars
        PropertyChanged "BlueComponent"
    End Property

    Private Sub UpdateColors(Index As Integer)
        Select Case Index
            Case 0:     m_RedComponent = Component(0).Value
                        PropertyChanged "RedComponent"
                        RaiseEvent RedChanged
            Case 1:      m_GreenComponent = Component(1).Value
                        PropertyChanged "GreenComponent"
                        RaiseEvent GreenChanged
            Case 2:     m_BlueComponent = Component(2).Value
                        PropertyChanged "BlueComponent"
                        RaiseEvent BlueChanged
        End Select
        Picture1.BackColor = RGB(Component(0).Value, Component(1).Value, Component(2).Value)
        Picture1.Refresh
        m_SelectedColor = m_RedComponent + CLng(m_GreenComponent) * 256 + CLng(m_BlueComponent) * 256 ^ 2
    End Sub

    Private Sub UpdateScrollbars()
        Component(0).Value = m_RedComponent
        Component(1).Value = m_GreenComponent
        Component(2).Value = m_BlueComponent
        Label4.Caption = m_RedComponent
        Label5.Caption = m_GreenComponent
        Label6.Caption = m_BlueComponent
    End Sub

    Private Sub UpdateValues()
        Label4.Caption = m_RedComponent
        Label5.Caption = m_GreenComponent
        Label6.Caption = m_BlueComponent
    End Sub

Download this Project

Back

©1999-2000 VBGreatone. All rights reserved.