The CColorPicker Class
The public CColorPicker class is a simple wrapper for the private FColorPicker form. As you saw with AllAbout earlier in this chapter, forms can’t be public and that’s just as well. The CColorPicker class hides all the form details that you don’t want users to see.
In the sample, a color picker dialog box pops up whenever you click the right mouse button. The MouseUp event procedure illustrates how CColorPicker changes the color:
Private Sub Form_MouseUp(Button As Integer, Shift As Integer, _
X As Single, Y As Single)
If Button = 2 Then
Dim getclr As New CColorPicker
Static clrLast As Long
' Load last color used
If clrLast <> 0& Then getclr.Color = clrLast
' Load dialog at given position and shape
getclr.Load Left + X, Top + Y, -chkWideForm
' Save chosen color for next time
clrLast = getclr.Color
' Change color of form and check boxes
AllColors clrLast
End If
End Sub
This color picker form can come in two shapes—the 16 by 3 cell shape familiar from Visual Basic version 4, and the 8 by 6 cell shape used in the current version. The Wide property controls the shape; the Color property sets the initial color and gets the selected color when the dialog box is finished. The Load command loads the dialog box and the dialog box doesn’t go away until the user selects a color or presses the escape key.
The implementation comes in two parts—CColorPicker and FColorPicker. CColorPicker just passes the work on to FColorPicker. The Load method gives you an idea of how simple this is:
Private frm As New FColorPicker
Sub Load(Optional ByVal Left As Single = -1#, _
Optional ByVal Top As Single = -1#, _
Optional ByVal Wide As Boolean = True)
frm.Wide = Wide
If Left <> -1# Then frm.Left = Left
If Top <> -1# Then frm.Top = Top
frm.Show vbModal
End Sub
The real work is done on the form. A quick summary of the implementation follows:
-
The form has its MinButton, MaxButton, and ControlBox properties
set to False and its Caption property left empty so that the form won’t have a title bar. The BorderStyle property is set to Fixed Single to prevent the user from resizing it. The ScaleMode property is set to Pixel so that everything can be measured exactly in pixels. AutoRedraw is set to False, which means that the form must handle its Paint event.
-
The InitArray procedure redimensions and initializes the color array in either a 16 by 3 or 8 by 6 format, depending on the Wide property.
-
Form_Resize sets the exact width and height so that you don’t need to size the form at design time.
-
Form_Paint draws the color boxes and fills them with the colors from the array.
-
Form_MouseDown calculates which color box is under the mouse pointer and draws a selection box around the color.
-
Form_MouseUp sets an internal variable with the selected color and unloads the form.
-
The Color Property Get procedure returns the selected color from its internal variable. The Color Property Let procedure searches for the color array entry that matches a given color and makes it the default. This allows you to initialize the form with the color that was selected the last time you loaded the form.
I won’t explain the code in detail, but the Form_Paint sub will give you the flavor:
Private Sub Form_Paint()
Dim ix As Long, iy As Long
' Draw colors in their boxes
FillStyle = vbSolid
For ix = 1 To ixMax
For iy = 1 To iyMax
FillColor = aColor(ix, iy)
Line (((ix - 1) * 17) + 1, _
((iy - 1) * 17) + 1)-Step(15, 15), , B
Next
Next
DrawSelection ixCur, iyCur, True
End Sub
The only other point I want to make about the FColorPicker form is that its properties are Friends. Instead of this:
Public Property Get Color() As Long
you define this:
Friend Property Get Color() As Long
This is a global optimization that you can add to any form that shares information by providing properties or methods. Think about it. Forms are always private. When you declare a “public” property on a form, it’s not really public in the same way that a class method can be public. Nobody outside your application or component can see it—which happens to be the definition of Friend. So from a user standpoint, Public and Friend have exactly the same effect in forms. But internally they work differently.
A form is actually a kind of class, and like all classes, it uses COM to make its methods and properties available to other modules. A standard module, on the other hand, doesn’t work through COM and can therefore make its procedures available more directly. The Friend keyword makes classes work more like standard modules. I don’t know the technical details, but you can see the results in the TimeIt application. In native code, a Friend property on a form works about five times faster than an equivalent Public property.
Generally, properties on forms are just about the last place you’d voluntarily spend time optimizing. The better performance certainly isn’t going to make any visible difference when loading an FColorPicker form, but as Joe Hacker says: “If you can get better performance for free, take it—whether you need it or not.”
You can see more of the code in COLORPICKER.FRM, which as noted in “Using the CAbout class,” resides in VisualCore rather than VBCore.