The Windows/Basic Way of Implementing Common Dialogs


Let’s compare several different approaches to common dialogs. I’ll start with one of the simpler dialogs, color selection, and show you several different ways to display it.


First, here’s the traditional technique using the CommonDialog control. This assumes that the control is embedded somewhere in a Form, UserControl, or PropertyPage:

Function OptionColor(Optional ByVal clr As Long = vbBlack) As Long
With dlgColor
' No VB constant for CC_SOLIDCOLOR, but it works
.Flags = cdlCCRGBInit Or CC_SOLIDCOLOR
' Make sure it's an RGB color
.Color = TranslateColor(clr)
.hWnd = hWnd
' Can only recognize cancel with error trapping
.CancelError = True
On Error Resume Next
.ShowColor
' Return color, whether successful or not
If Err Then
OptionColor = clr
Else
OptionColor = .Color
End If
End With
End Function

This is a little bit messy. You have to put constants into a Flags property to control the behavior of the dialog, and Visual Basic doesn’t supply all the possible constants. Fortunately, the control is a very thin wrapper for Windows API functions and it recognizes any constant you can find in the API documentation. Handling the Cancel button is atrocious, but it used to be even worse. Those of you who used the first version of the CommonDialog control know what I’m talking about, and those of you who didn’t use it don’t want to know.


The Dialog Automation Objects version is much better:

Function OptionColor(Optional ByVal clr As Long = vbBlack) As Long
Dim choose As New ChooseColor
With choose
' Make sure it's an RGB color
.Color = TranslateColor(clr)
.hWnd = hWnd
' No property to specify solid colors.
' Return color, whether successful or not.
If .Show Then
OptionColor = choose.Color
Else
OptionColor = clr
End If
End With
End Function

Properties are used to define the characteristics of the dialog. You set them before. You read them afterward. But the designer didn’t give me the one property I wanted—displaying only solid colors, as opposed to displaying both solid and dithered colors. The RichTextBox editor won’t accept dithered colors for the text background or foreground, so why display them? Because the designer was trying to make things easy for most users, and if his or her choices don’t match yours or mine, we’re out of luck.


Finally, here’s my API wrapper version:

Function OptionColor(Optional ByVal clr As Long = vbBlack) As Long
' Make sure it's an RGB color
clr = TranslateColor(clr)
' Choose a solid color
Call VBChooseColor(Color:=clr, AnyColor:=False, Owner:=hWnd)
' Return color, whether successful or not
OptionColor = clr
End Function

Instead of properties, I use named arguments. I’m the designer, so of course I give myself the parameters I need, but perhaps you want different parameters—ones that I didn’t think anyone would ever want. In this example, my code is shorter, but that’s not always the case, and anyway, I prefer the more structured interface of the dialog objects. I’d drop my version in a minute if the dialog objects did everything I need.


There’s one other option for displaying common dialogs—create your own versions. I’ll do that later with the Find and Replace dialog boxes. I’ll also build a Picture display dialog box that looks sort of like the File Open dialog box later in this chapter.