A Visual Basic Class Wrapper for Common Dialog Functions

Steve Kirk
Microsoft Developer Network Technology Group

September 4, 1996

Click to open or copy the files in the COMDLG sample application for this technical article.

Abstract

This article explains how to create a class wrapper in Visual Basic® version 4.0 to encapsulate the Common Dialog functions in the Win32® application programming interface (API). The Common Dialog functions provide a standard set of dialog boxes for operations such as opening, saving, and printing files, or selecting colors and fonts. The class creates objects that, with the exception of an object instantiation line, are code-compatible with Visual Basic's Common Dialog control.

Control or Class Wrapper: Which Tool to Use?

Before we go into the details of how to create a class wrapper, let's answer the question of why you should go to all the trouble of creating one when it's so easy to just use the Visual Basic® Common Dialog control.

The Common Dialog control provides a Component Object Model (COM) interface to the common dialogs by using the properties and methods of a control on a form. Compare the Common Dialog control, which must be a connected to form, to a clock that's designed to be permanently fastened to a wall. A wall clock works just fine in a classroom or train station but makes a pretty clunky alarm clock. It's good that there are other kinds of clocks available, like table clocks and wrist watches—clocks that work without a wall and that don't require you to be in a certain room to check the time! To continue the analogy, in software design, a Common Dialog object that is independent of a form will lend itself to cleaner solutions than a control that is attached to a form. This solution avoids two problems:

A more general distinction between an in-process server and an OLE control is that the former can be written in Visual Basic while the latter must be written in C or C++. The server can be developed either as a class module, which can be added to a project as source code, or as a COM dynamic-link library (DLL), which has the dual advantages of hiding source code and conserving resources when multiple applications share functionality.

Common Dialog Control vs. Common Dialog Class

Code Comparison—Using the Open File Dialog Box

The following code snippet shows how a program might be assigned a filename using the Common Dialog control. This example assumes that the Visual Basic project contains a form called frmMain that contains the Common Dialog control called ctlCommonDialog.

'Display the File Open dialog.
frmMain.ctlCommonDialog.ShowOpen

'Display filename in a message box.
MsgBox("Selected file is " & frmMain.ctlCommonDialog.FileName)

Now let's see how to use an object instantiated from the Common Dialog class to assign a filename. The Visual Basic project is assumed to include either a class module named clsCommonDialog or a reference to an in-process server that creates clsCommonDialog objects.

'Create the CommonDialog object.
Dim objCommonDialog As New clsCommonDialog

'Display the File Open dialog.
objCommonDialog.ShowOpen

'Display filename in a message box.
MsgBox("Selected file is " & objCommonDialog.FileName)

Note that, with the exception of the instantiation line and object name differences, the code is the same.

Differences in Files to be Distributed with Applications

The Win32® Common Dialog API functions are located in COMDLG32.DLL, which must be in the Windows system directory for either common dialog interface to function.

Programs using the Visual Basic Common Dialog control require that COMDLG32.OCX be available and correctly registered.

If the Common Dialog class is included as a class module in a Visual Basic project, no other files are required. If the class is compiled as an in-process server, the resulting DLL will need to be available at run time and must be correctly registered.

Class/Object Map

The following tables describe the methods and public properties, respectively, for the Common Dialog class/object.

Table 1. Methods

Procedure Description
Public Sub ShowColor Provides the class ShowColor method
Public Sub ShowFont Provides the class ShowFont method
Public Sub ShowHelp Provides the class ShowHelp method
Public Sub ShowOpen Provides the class ShowOpen method
Public Sub ShowPrinter Provides the class ShowPrinter method
Public Sub ShowSave Provides the class ShowSave method

Table 2. Public Properties

Public Property Name Access Private Internal Buffer
Action Read Only iAction
APIReturn Read Only lAPIReturn
CancelError Read/Write bCancelError
Color Read/Write lColor
Copies Read/Write lCopies
DefaultExt Read/Write sDefaultExt
DialogTitle Read/Write sDialogTitle
ExtendedError Read Only lExtendedError
FileName Read/Write sFileName
FileTitle Read/Write sFileTitle
Filter Read/Write sFilter
FilterIndex Read/Write iFilterIndex
Flags Read/Write lFlags
FontBold Read/Write bFontBold
FontItalic Read/Write bFontItalic
FontName Read/Write sFontName
FontSize Read/Write lFontSize
FontStrikethru Read/Write bFontStrikethru
FontUnderline Read/Write bFontUnderline
FromPage Read/Write lFromPage
hdc Read/Write lhdc
HelpCommand Read/Write lHelpCommand
HelpContext Read/Write sHelpContext
HelpFile Read/Write sHelpFile
HelpKey Read/Write sHelpKey
InitDir Read/Write sInitDir
Max Read/Write lMax
MaxFileSize Read/Write lMaxFileSize
Min Read/Write lMin
Object Read Only objObject
PrinterDefault Read/Write iPrinterDefault
ToPage Read/Write lToPage

Construction of the Class

Creating the Class Module

  1. From the Insert menu, select Class Module. A new window is created and named Class1.

  2. Press F4 to bring up the Properties dialog box.

  3. Type clsCommonDialog in the Name property. In order to use the class as a source code module that can be included in any project, set the Instancing property to 0 - Not Creatable and the Public property to False. To create an OLE DLL, set the Instancing property to 2 - Creatable MultiUse and the Public property to True.

Declarations

These Declare Function statements create an interface between the Visual Basic class module and the Common Dialog functions in COMDLG32.DLL. Use of the PRIVATE option hides these functions from everything outside the class module.

'API function called by ShowColor method
Private Declare Function ChooseColorA Lib "comdlg32.dll" (pChoosecolor As tChooseColor) As Long

'API function called by ShowFont method
Private Declare Function ChooseFontA Lib "comdlg32.dll" (pChoosefont As tChooseFont) As Long

'API function inside ShowHelp method
Private Declare Function WinHelpA Lib "user32" (ByVal hwnd As Long, ByVal lpHelpFile As String, ByVal wCommand As Long, ByVal dwData As Long) As Long

'API function called by ShowOpen method
Private Declare Function GetOpenFileNameA Lib "comdlg32.dll" (pOpenfilename As tOpenFilename) As Long

'API function called by ShowSave method
Private Declare Function GetSaveFileNameA Lib "comdlg32.dll" (pOpenfilename As tOpenFilename) As Long

'API function called by ShowPrinter method
Private Declare Function PrintDlgA Lib "comdlg32.dll" (pPrintdlg As tPrintDlg) As Long

'API function to retrieve extended error information
Private Declare Function CommDlgExtendedError Lib "comdlg32.dll" () As Long

'API memory functions
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, ByVal dwBytes As Long) As Long

Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long

Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long

Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long

Private Declare Sub CpyMemValAdrFromRefAdr Lib "kernel32" Alias "RtlMoveMemory" (ByVal hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)

Private Declare Sub CpyMemRefAdrFromValAdr Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, ByVal hpvSource As Any, ByVal cbCopy As Long)

Property Procedures

The property procedures assign and retrieve an object's properties.

Each property that is exposed has a Public Property Get procedure corresponding to the property name.

Public Property Get FileName() As String
'Return object's FileName property.
FileName = sFileName
End Property

Each property that is writeable has a Public Property Let or Public Property Set corresponding to the property name. Object type properties have a Public Property Set. Non-object type properties have a Public Property Let.

Public Property Let FileName(vNewValue As String)
'Handle assignment of object's FileName property.
sFileName = vNewValue
End Property

Common Dialog Methods

Public procedures in the class module are exposed as methods on objects instantiated from the Common Dialog class. ShowColor, ShowFont, ShowHelp, ShowOpen, ShowPrinter and ShowSave are the methods exposed.

ShowColor

The ShowColor method creates a Color common dialog box (Figure 1) that enables the user to select a color.

Figure 1. The Color common dialog box, created by ShowColor

In the following code, Public Sub ShowColor() provides the ShowColor method. ShowColor() handles the interface between Common Dialog Object property data and the Win32® ChooseColor function.

Public Sub ShowColor()
'Provide the ShowColor method and interface with the Win32 ChooseColor function.

Dim vChooseColor As tChooseColor
Dim aCustomColors(15) As Long
Dim iColorMember As Integer
Dim lCustomColorSize As Long
Dim lCustomColorAddress As Long
Dim lMemHandle As Long
Dim lReturn As Long

On Error GoTo ErrShowColor

Initialize the private property buffers for the Action, APIReturn, and ExtendedError properties.

iAction = CLSCD_SHOWCOLOR
lApiReturn = 0  'APIReturn property
lExtendedError = 0  'ExtendedError property

Prepare vChooseColor for the Win32 ChooseColor function. Incorporate the Color property.

vChooseColor.lStructSize = Len(vChooseColor)
vChooseColor.rgbResult = lColor
' Fill custom colors array with all white.
For iColorMember = 0 To 15
    aCustomColors(iColorMember) = &HFFFFFF
Next
' Get size of memory needed for custom colors.
lCustomColorSize = Len(aCustomColors(0)) * 16
' Get a global memory block to hold a copy of the custom colors.
lMemHandle = GlobalAlloc(GHND, lCustomColorSize)
If lMemHandle Then
    ' Lock the custom color's global memory block.
    lCustomColorAddress = GlobalLock(lMemHandle)
    If lCustomColorAddress Then
        'Copy custom colors to the global memory block.
        CpyMemValAdrFromRefAdr lCustomColorAddress, _
        aCustomColors(0), lCustomColorSize
        vChooseColor.lpCustColors = lCustomColorAddress
        'flags As Long
        vChooseColor.Flags = lFlags

Call the Win32 ChooseColor function. The return value is saved as the APIReturn property.

        lApiReturn = ChooseColorA(vChooseColor)

Handle the return from ChooseColor. Update the Color property.

        Select Case lApiReturn
            Case CLSCD_USERCANCELED
                If bCancelError = True Then
                    'Clean up memory first.
                    lReturn = GlobalUnlock(lMemHandle)
                    lReturn = GlobalFree(lMemHandle)
                    'Generate an error.
                    On Error GoTo 0
                    Err.Raise Number:=CLSCD_ERRNUMUSRCANCEL, _
                        Description:=CLSCD_ERRDESUSRCANCEL
                    Exit Sub
                End If
            Case CLSCD_USERSELECTED
                'Clean up memory first.
                lReturn = GlobalUnlock(lMemHandle)
                lReturn = GlobalFree(lMemHandle)
                'Update property buffer.
                lColor = vChooseColor.rgbResult
            Case Else   'an error occured
                'Clean up memory first.
                lReturn = GlobalUnlock(lMemHandle)
                lReturn = GlobalFree(lMemHandle)
                'call CommDlgExtendedError
                lExtendedError = CommDlgExtendedError
        End Select
    Else
        lReturn = GlobalFree(lMemHandle)
    End If
End If
Exit Sub

ErrShowColor:
'Clean up memory first
lReturn = GlobalUnlock(lMemHandle)
lReturn = GlobalFree(lMemHandle)
Exit Sub

End Sub

ShowFont

The ShowFont method creates a Font common dialog box (Figure 2) that enables the user to choose attributes for a logical font. These attributes include a typeface name, style (bold, italic, or regular), point size, effects (underline, strikeout, and text color) and script (or character set).

Figure 2. The Font common dialog box, created by ShowFont

In the code below, Public Sub ShowFont provides the ShowFont method. ShowFont() handles the interface between Common Dialog object property data and the Win32 ChooseFont function.

Public Sub ShowFont()
'Provide the ShowFont method and interface with the Win32 ChooseFont function.

Dim vLogFont As tLogFont
Dim vChooseFont As tChooseFont
Dim lLogFontSize As Long
Dim lLogFontAddress As Long
Dim lMemHandle As Long
Dim lReturn As Long
Dim sFont As String
Dim lBytePoint As Long

On Error GoTo ShowFontError

Initialize the private property buffers for the Action, APIReturn, and ExtendedError properties.

iAction = CLSCD_SHOWFONT    'Action property
lApiReturn = 0  'APIReturn property
lExtendedError = 0  'ExtendedError property

Prepare vChooseFont for the Win32 ChooseFont function. Incorporate the FontBold, FontItalic, FontUnderline, FontStrikethru, FontSize, and Flags properties.

'vLogFont.lfWeight As Long - init from FontBold property
If bFontBold = True Then
    vLogFont.lfWeight = FW_BOLD
End If
'vLogFont.lfItalic As Byte - init from FontItalic property
If bFontItalic = True Then
    vLogFont.lfItalic = 1
End If
'vLogFont.lfUnderline As Byte - init from FontUnderline property
If bFontUnderline = True Then
    vLogFont.lfUnderline = 1
End If
'vLogFont.lfStrikeOut As Byte - init from FontStrikethru property
If bFontStrikethru = True Then
    vLogFont.lfStrikeOut = 1
End If
'vChooseFont.lStructSize As Long
vChooseFont.lStructSize = Len(vChooseFont)
'vChooseFont.lpLogFont As Long
lLogFontSize = Len(vLogFont)
' Get a global memory block to hold a copy of vLogFont - exit on failure.
lMemHandle = GlobalAlloc(GHND, lLogFontSize)
' If GlobalAlloc failed, exit
If lMemHandle Then
    ' Lock vLogFont's global memory block - exit on failure
    lLogFontAddress = GlobalLock(lMemHandle)
    ' If GlobalLock failed, free memory and exit.
    If lLogFontAddress Then
        'Copy vLogFont to the global memory block.
        CpyMemValAdrFromRefAdr lLogFontAddress, vLogFont, lLogFontSize
        vChooseFont.lpLogFont = lLogFontAddress
        'vChooseFont.iPointSize As Long - init from FontSize property
        vChooseFont.iPointSize = lFontSize * 10
        'vChooseFont.flags As Long - init from Flags property
        vChooseFont.Flags = lFlags      

Call the Win32 ChooseFont function. The return value is saved as the APIReturn property.

        lApiReturn = ChooseFontA(vChooseFont)    'store to APIReturn property

Handle the return value from ChooseFont. Update the FontBold, FontItalic, FontUnderline, FontStrikethru, FontName, and FontSize properties.

        Select Case lApiReturn
            Case CLSCD_USERCANCELED
                If bCancelError = True Then
                    'Clean up memory first.
                    lReturn = GlobalUnlock(lMemHandle)
                    lReturn = GlobalFree(lMemHandle)
                    'Generate an error.
                    On Error GoTo 0
                    Err.Raise Number:=CLSCD_ERRNUMUSRCANCEL, _
                        Description:=CLSCD_ERRDESUSRCANCEL
                    Exit Sub
                End If
            Case CLSCD_USERSELECTED
                ' Copy global memory block to vLogFont.
                CpyMemRefAdrFromValAdr vLogFont, lLogFontAddress, lLogFontSize
                'Clean up memory.
                lReturn = GlobalUnlock(lMemHandle)
                lReturn = GlobalFree(lMemHandle)
                'vLogFont.lfWeight As Long  - store to FontBold property
                If vLogFont.lfWeight >= FW_BOLD Then
                    bFontBold = True
                Else
                    bFontBold = False
                End If
                'vLogFont.lfItalic As Byte - store to FontItalic property
                If vLogFont.lfItalic = 1 Then
                    bFontItalic = True
                Else
                    bFontItalic = False
                End If
                'vLogFont.lfUnderline As Byte - store to FontUnderline property
                If vLogFont.lfUnderline = 1 Then
                    bFontUnderline = True
                Else
                    bFontUnderline = False
                End If
                'vLogFont.lfStrikeOut As Byte - store to FontStrikethru property
                If vLogFont.lfStrikeOut = 1 Then
                    bFontStrikethru = True
                Else
                    bFontStrikethru = False
                End If
                'vLogFont.lfFaceName(LF_FACESIZE) As Byte - store to FontName
                'property
                FontName = sByteArrayToString(vLogFont.lfFaceName())
                'vChooseFont.iPointSize As Long - store to FontSize property
                lFontSize = CLng(vChooseFont.iPointSize / 10)
            Case Else   'An error occurred.
                'Clean up memory first.
                lReturn = GlobalUnlock(lMemHandle)
                lReturn = GlobalFree(lMemHandle)
                'call CommDlgExtendedError
                lExtendedError = CommDlgExtendedError   'Store to ExtendedError  
                'property
        End Select
    Else
        lReturn = GlobalFree(lMemHandle)
        Exit Sub
    End If
End If
Exit Sub

ShowFontError:
'Clean up memory first.
lReturn = GlobalUnlock(lMemHandle)
lReturn = GlobalFree(lMemHandle)
Exit Sub

End Sub

ShowHelp

The ShowHelp method displays the help file specified in the HelpFile property.

In the following code, Public Sub ShowHelp() provides the ShowHelp method. ShowHelp() handles the interface between Common Dialog Object property data and WINHELP.EXE.

Public Sub ShowHelp()
'Provide the ShowHelp method and interface with winhelp.exe.

Dim sHelpFileBuff As String
Dim lData As Long

On Error GoTo ShowHelpError

Initialize the private property buffers for the Action, APIReturn, and ExtendedError properties.

iAction = CLSCD_SHOWHELP  'Action property
lApiReturn = 0  'APIReturn property
lExtendedError = 0  'ExtendedError property

Prepare the parameters for the Win32 WinHelp function.

'sHelpFile is a null terminated string
sHelpFileBuff = sHelpFile & Chr$(0)

Call the Win32 WinHelp function. The return value is saved as the APIReturn property.

lApiReturn = WinHelp(lhdc, sHelpFile, lHelpCommand, lData)

Handle the return value from WinHelp.

Select Case lApiReturn    
    Case CLSCD_USERCANCELED
        'call CommDlgExtendedError
        lExtendedError = CommDlgExtendedError   ' - store to ExtendedError
        'property
    Case Else
        'call CommDlgExtendedError
        lExtendedError = CommDlgExtendedError
End Select
    
Exit Sub

ShowHelpError:
Exit Sub

End Sub

ShowOpen/ShowSave

The ShowOpen and ShowSave functions create an Open or Save common dialog box (Figure 3) that lets the user specify the drive, directory, and the name of a file or set of files to open or save.

Figure 3. The Open Dialog Box, created by ShowOpen

The ShowOpen and ShowSave methods are provided by public subs that call ShowFileDialog. ShowFileDialog handles the interface between Common Dialog object property data and the Win32 GetOpenFileName and GetSaveFileName functions.

Public Sub ShowOpen()
'Provide the ShowOpen method.
ShowFileDialog (CLSCD_SHOWOPEN)
End Sub

Public Sub ShowSave()
'Provide the ShowSave method.
ShowFileDialog (CLSCD_SHOWSAVE)
End Sub

Private Sub ShowFileDialog(ByVal iAction As Integer)
'Interface with Win32 GetOpenFileName and GetSaveFileName functions.

Dim vOpenFile As tOpenFilename
Dim lMaxSize As Long
Dim sFileNameBuff As String
Dim sFileTitleBuff As String

On Error GoTo ShowFileDialogError

Initialize the private property buffers for the Action, APIReturn, and ExtendedError properties.

iAction = iAction  'Action property
lApiReturn = 0  'APIReturn property
lExtendedError = 0  'ExtendedError property

Prepare vOpenFile with data from the Filter, FilterIndex, MaxFileSize, FileName, FileTitle, InitDir, DialogTitle, Flags, and DefaultExt properties.

'vOpenFile.lStructSize As Long
vOpenFile.lStructSize = Len(vOpenFile)
'vOpenFile.lpstrFilter As String - init from Filter property
vOpenFile.lpstrFilter = sAPIFilter(sFilter)
'vOpenFile.iFilterIndex As Long - init from FilterIndex property
vOpenFile.iFilterIndex = iFilterIndex
'vOpenFile.lpstrFile As String
'Determine size of buffer from MaxFileSize property.
If lMaxFileSize > 0 Then
    lMaxSize = lMaxFileSize
Else
    lMaxSize = CLSCD_MAXFILESIZE
End If
'vOpenFile.lpstrFile As Long - init from FileName property
'Prepare sFileNameBuff.
sFileNameBuff = Space(lMaxSize + 1)
LSet sFileNameBuff = sFileName & vbNullChar
vOpenFile.lpstrFile = sFileNameBuff
'nMaxFile As Long - init from MaxFileSize property
vOpenFile.nMaxFile = lMaxFileSize
'lpstrFileTitle As String - init from FileTitle property
'Prepare sFileTitleBuff.
sFileTitleBuff = Space(lMaxSize + 1)
LSet sFileTitleBuff = vbNullChar
vOpenFile.lpstrFileTitle = sFileTitleBuff
'vOpenFile.lpstrInitialDir As String - init from InitDir property
vOpenFile.lpstrInitialDir = sInitDir
'vOpenFile.lpstrTitle As String - init from DialogTitle property
vOpenFile.lpstrTitle = sDialogTitle
'vOpenFile.flags As Long - init from Flags property
vOpenFile.Flags = lFlags
'vOpenFile.lpstrDefExt As String - init from DefaultExt property
vOpenFile.lpstrDefExt = sDefaultExt

Call either the Win32 GetOpenFileName or GetSaveFileName function, depending on the iAction parameter. The return value is saved as the APIReturn property.

Select Case iAction
    Case CLSCD_SHOWOPEN
        lApiReturn = GetOpenFileNameA(vOpenFile)
    Case CLSCD_SHOWSAVE
        lApiReturn = GetSaveFileNameA(vOpenFile)
    Case Else   'unknown action
        Exit Sub
End Select

Handle the return from the Win32 function. Update the FileName and FileTitle properties.

Select Case lApiReturn
    Case CLSCD_USERCANCELED
        If bCancelError = True Then
            'Generate an error.
            On Error GoTo 0
            Err.Raise Number:=CLSCD_ERRNUMUSRCANCEL, _
                Description:=CLSCD_ERRDESUSRCANCEL
            Exit Sub
        End If
    Case CLSCD_USERSELECTED
        'sFileName gets part of vOpenFile.lpstrFile to the left of first Chr$(0)
        sFileName = sLeftOfNull(vOpenFile.lpstrFile)
        sFileTitle = sLeftOfNull(vOpenFile.lpstrFileTitle)
    Case Else   'an error occured
        'call CommDlgExtendedError
        lExtendedError = CommDlgExtendedError    
End Select
Exit Sub

ShowFileDialogError:
Exit Sub

End Sub

ShowPrinter

The ShowPrinter method displays a Print dialog box (Figure 4) or a Print Setup dialog box. The Print dialog box makes it possible for the user to specify the properties of a particular print job. The Print Setup dialog box makes it possible for the user to select additional job properties and configure the printer.

Figure 4. Print dialog box

In the following code, Public Sub ShowPrinter() provides the ShowPrinter method. ShowPrinter() handles the interface between Common Dialog Object property data and the Win32 PrintDlg function.

Public Sub ShowPrinter()
'Provide the ShowPrinter method, interface with Win32 PrintDlg function.

Dim vPrintDlg As tPrintDlg

On Error GoTo ShowPrinterError

Initialize the private property buffers for the Action, APIReturn, and ExtendedError properties.

iAction = CLSCD_SHOWPRINT  'Action property
lApiReturn = 0  'APIReturn property
lExtendedError = 0  'ExtendedError property

Prepare vPrintDlg data for the Win32 ShowPrinter function. Incorporate the Flags, FromPage, ToPage, MinPage, MaxPage, and Copies properties.

'lStructSize As Long
vPrintDlg.lStructSize = Len(vPrintDlg)
'hdc As Long - init from hDC property
vPrintDlg.hdc = lhdc
'flags As Long - init from Flags property
vPrintDlg.Flags = lFlags
'nFromPage As Integer - init from FromPage property
vPrintDlg.nFromPage = lFromPage
'nToPage As Integer - init from ToPage property
vPrintDlg.nToPage = lToPage
'nMinPage As Integer - init from Min property
vPrintDlg.nMinPage = lMin
'nMaxPage As Integer - init from Max property
vPrintDlg.nMaxPage = lMax
'nCopies As Integer - init from Copies property
vPrintDlg.nCopies = lCopies

Call the Win32 PrintDlg function. The return value is saved as the APIReturn property.

lApiReturn = PrintDlgA(vPrintDlg)

Handle the return from PrintDlg. Update the FromPage, ToPage, Min, Max, and Copies properties.

Select Case lApiReturn
   Case CLSCD_USERCANCELED
      If bCancelError = True Then
         'generate an error
          On Error GoTo 0
          Err.Raise Number:=CLSCD_ERRNUMUSRCANCEL, _
             Description:=CLSCD_ERRDESUSRCANCEL
            Exit Sub
      End If
   Case CLSCD_USERSELECTED
      'nFromPage As Integer - store to FromPage property
      lFromPage = vPrintDlg.nFromPage
      'nToPage As Integer - store to ToPage property
      lToPage = vPrintDlg.nToPage
      'nMinPage As Integer - store to Min property
      lMin = vPrintDlg.nMinPage
      'nMaxPage As Integer - store to Max property
      lMax = vPrintDlg.nMaxPage
      'nCopies As Integer - store to Copies property
      lCopies = vPrintDlg.nCopies
   Case Else   'an error occured
      'call CommDlgExtendedError
      lExtendedError = CommDlgExtendedError   'store to ExtendedError property
End Select
Exit Sub

ShowPrinterError:
Exit Sub

End Sub

COMDLG: A Formless Common Dialog Example

This example cycles through all of the Common Dialog functions until the user cancels. To try it out:

  1. Create a new project.

  2. Add the COMDLG.CLS file.

  3. Remove the default Form1 from the project.

  4. Insert a new module and paste the code below into the Declarations section.

  5. Set the project startup option from Form1 to Sub Main.

  6. Press F5 to run.
Sub Main()
Dim objCommonDialog As New clsCommonDialog

On Error GoTo ErrMain
objCommonDialog.CancelError = True
objCommonDialog.HelpFile = "win.hlp"

While True
   objCommonDialog.ShowColor
   objCommonDialog.ShowFont
   objCommonDialog.ShowHelp
   objCommonDialog.ShowOpen
   objCommonDialog.ShowPrinter
   objCommonDialog.ShowSave
Wend

Exit Sub
ErrMain:
   End
End Sub

Conclusion

The Win32 Common Dialog object is easier to use than the Visual Basic Common Dialog control because it doesn't need to be a part of a form. This makes it easier to organize projects for clarity and efficient operation. The Common Dialog object provides the same methods and properties as the Common Dialog control; it can be used to replace the Common Dialog control in existing projects with very little modification to code.