home *** CD-ROM | disk | FTP | other *** search
-
- Microsoft Foundation Classes Microsoft Corporation
- Technical Notes
-
- #13 : Using the standard dialog classes
-
-
- This note describes the use of the standard dialog classes provided
- with MFC. The classes are CFileDialog, CFontDialog, CColorDialog,
- CPrintDialog, and CFindReplaceDialog. They provide standard user interface
- objects for your application. The class declarations for these
- classes can be found in the source file \C700\MFC\INCLUDE\AFXDLGS.H.
- =============================================================================
-
-
- Requirements
- ============
- You may use these classes for any MFC application. Although these
- classes use the Windows 3.1 COMMDLG functions, they do not require
- Windows 3.1 to run. You must redistribute COMMDLG.DLL with your
- application and install the DLL in the user's Windows 3.0 system directory.
- When building an application that uses these classes, you must
- link with the library COMMDLG.LIB, which is part of the Windows SDK
- installation.
-
-
- General Use
- ===========
- These dialogs classes may be used in one of two ways. You can use them
- "as is" and supply the necessary arguments to the constructor to
- customize the dialogs to suit your needs. You might also
- consider deriving from these classes and providing a specific constructor
- tailored to your needs. In either case, these dialogs act
- like standard MFC dialogs, since they derive from CDialog (either
- directly or indirectly.) You can use message maps and customize
- these dialogs even more.
-
- COMMDLG dialog APIs interface with the application code via
- a parameter block structure. The MFC dialog classes provide
- public access to this structure, which may be accessed at any
- time to permit maximum customization. On the other hand, MFC
- provides sensible defaults for most of the fields in the parameter
- block so that you do not need to worry about them. These structures
- are described in the online Windows 3.1 API reference.
-
-
- Examples
- ========
- The MULTIPAD sample application uses the CFileDialog, CFontDialog,
- and CPrintDialog. The CHART application uses CFileDialog
- and CPrintDialog. The MDI application uses the CColorDialog. In
- addition, the OLE classes use the standard CFileDialog for
- implementing standard OLE user interface objects.
-
-
- CFileDialog
- ===========
- The CFileDialog class encapsulates the OPENFILENAME structure
- and the two Windows APIs GetOpenFileName and GetSaveFileName. This
- dialog box is used to obtain from a user either a new file name
- or the name of an existing file to open. CFileDialog is a modal
- dialog and derives from the class CModalDialog.
-
- To use a CFileDialog class object, create an object using the CFileDialog
- constructor. The arguments to the constructor are below, note
- that several have default values:
-
- bOpenFileDialog set to TRUE for file open dialog, FALSE for
- a file save dialog
- lpszDefExt is the default extension, if a user does not
- include a file extension, this is
- automatically appended.
- lpszFileName is the initial file name (defaults to NULL)
- dwFlags is a set of flags that you can supply
- that allow you to customize the dialog box.
- See the online Windows API reference
- (OPENFILESTRUCT) for more information
- (defaults to OFN_HIDEREADONLY |
- OFN_OVERWRITEPROMPT)
- lpszFilter is a series of pairs of strings that specify
- filters the user may apply to the files.
- See below (defaults to NULL)
- pParentWnd is a pointer to a parent Window. This is
- used only when routing customized help
- messages (defaults to NULL.)
-
- The lpszFilter is used to display a possible list of suffixes. For
- example Microsoft Excel permits users to open *.XLC and *.XLS
- (and many others). The filter for Excel would look something
- like the following:
-
- char BASED_CODE szFilter[] =
- "Chart Files (*.xlc)|*.xlc|Worksheet Files (*.xlm)|*.xlm|All Files (*.*)|*.*||"
-
- Note the use of '|' to separate the components of the filter. Also
- note that the entire filter ends with two '|'. This is the
- standard MFC syntax for specifying filters. Also, note that the
- entire string is a standard NULL terminated C string, though you
- can always use an MFC CString object.
-
- Once the dialog has been constructed, you are free to modify the
- public member variable m_ofn, which is an OPENFILENAME structure.
- You may manually set any flags or fields that you need. When you
- are ready to prompt the user call the DoModal function (this is
- a virtual function derived from CModalDialog.) The user is then
- prompted for a file name (either an existing file or new file,
- depending on the bOpenFileDialog constructor parameter.) When
- the user clicks OK, CANCEL, or selected the CLOSE option from the
- dialogs System Menu, control is returned to your application. The
- return value from DoModal indicates success (IDOK) or
- failure (IDCANCEL.) If the return value is IDCANCEL, either the
- user closed the dialog or clicked CANCEL, or there was an error
- in the parameter block. If you suspect an error, you can call
- the CommDlgExtendedError API to learn more about the problem.
- CommDlgExtendedError function returns 0 if there was no error.
- This function differs from the standard OnOK and OnCancel functions
- in that it is possible to force the user to change actions, whereas
- OnOK and OnCancel are notifications that you must accept.
-
- If the user chose a file name, then you can continue processing.
- The CFileDialog class provides a number of helper functions to
- retrieve information regarding the users choice:
-
- GetPathName retrieves the fully qualified path name of the
- selected file (suitable to use with CFile)
- GetFileName retrieves just the file name without an extension
- GetFileExt retrieves only the file extension (without a '.')
- GetFileTitle retrieves the preferred title of the file, which
- should be used as the title text of the frame window
- GetReadOnlyPref returns TRUE if the user checked the read-only
- option. If this is TRUE, you should open the file
- with read-only permissions.
-
- There are also several "callback" functions that you may respond
- to in your derived CFileDialog class. You do not need message map
- entries for these, since they are standard virtual functions.
-
- OnShareViolation this function is called when a network
- sharing violation occurs while processing
- the dialog. See OPENFILENAME in the Windows
- API for more information.
- OnLBSelChangeNotify this function is called whenever the
- user changes the selection(s) in the file
- list. You can use this message if you
- need to do extra work when a file is
- a potential selection, such as calculating
- disk space required, or displaying
- file access rights.
- OnFileNameOK this function is called when the user
- selects OK. You can validate the file name
- and determine if the user can continue. If
- you return TRUE, be sure to indicate to the
- user the problem with the selected file(s.)
-
- One other technique available to customize the CFileDialog is to
- introduce a message map in a derived class and to handle messages
- just as you would for any other dialog. For example, you can modify
- the dialog background color or handle the command messages for
- a new control (the .RC file for the dialog is included.)
-
-
- CFontDialog
- ===========
- The CFontDialog class provides support for a standard dialog
- that permits a user to choose a font. The dialog makes use
- of the COMMDLG structure CHOOSEFONT and the API ChooseFont.
- CFontDialog is a modal dialog derived from the CModalDialog class.
-
- To use a CFontDialog class object, create an object using the CFontDialog
- constructor. The arguments to the constructor are below, note
- that several have default values:
-
- lplfInitial the initial settings of the dialog box (defaults
- to NULL)
- dwFlags is a set of flags that you can use to customize
- the function and appearance of the dialog. See
- the CHOOSEFONT structure reference for more
- information on possible values. (defaults to
- CF_EFFECTS | CF_SCREENFONTS)
- hdcPrinter if supplied is a CDC for the printer for which fonts
- are to be selected (defaults to NULL)
- pParentWnd is a pointer to a parent Window. This is
- used only when routing customized help
- messages (defaults to NULL)
-
- As with the CFileDialog class, once the object has been constructed
- you are free to modify the CHOOSEFONT structure, m_cf, in order
- to customize the dialog box fully. After any further customization,
- you call the member function DoModal, which will return either
- IDOK or IDCANCEL. If the return value is IDCANCEL, the user clicked
- on CANCEL or there was an initialization error in the dialog. You
- may use the CommDlgExtendedError function to determine if there
- was an initialization error. If the user selected OK the IDOK value
- is returned. The CFontDialog class provides a number of helper functions
- for extracting information out of the dialog:
-
- GetFaceName returns the face name of the font
- GetStyleName returns the style name of the font
- GetSize returns the point size in 1/10ths of a point
- GetColor returns the color of the selected font
- GetWeight returns the weight of the font
- IsStrikeout returns TRUE if the strikeout effect was selected
- IsUnderline returns TRUE if the underline effect was selected
- IsBold returns TRUE if the weight is equal to FW_BOLD
- IsItalic returns TRUE if the font is italic
-
- In addition, the member variable m_lf is the LOGFONT descriptor
- of the font, which can be used in a CreateFontIndirect call,
- or accessed directly.
-
- You may customize the dialog by deriving your own class from CFontDialog
- and using a message map to handle any messages. You can also use
- the CFontDialog::GetCurrentFont member function to determine the
- currently selected font while in a message handler.
-
-
- CColorDialog
- ============
- The CColorDialog class provides support for a standard dialog
- that permits a user to choose/create a color. The dialog makes use
- of the COMMDLG structure CHOOSECOLOR and the API ChooseColor.
- CColorDialog is a modal dialog derived from the CModalDialog class.
-
- CColorDialog is used just like CFontDialog. The COMMDLG structure
- that is used for customizing the dialog is CHOOSECOLOR, and it
- can be modified after construction of the object and before
- DoModal is called. The arguments to the constructor are as
- follows:
-
- clrInit is a COLORREF that is the initial color selection
- (defaults to RGB(0,0,0))
- dwFlags is a set of flags that you can use to customize
- the function and appearance of the dialog. See
- the CHOOSECOLOR structure reference for more
- information on possible values. (defaults to 0)
- pParentWnd is a pointer to a parent Window. This is
- used only when routing customized help
- messages (defaults to NULL.)
-
- In addition, the CColorDialog permits the user to define up to 16
- custom colors. The CColorDialog saves these custom colors between
- invocations of the dialog in the static member variable clrSavedCustom.
- If you wish to save these colors between executions of the application,
- then you must do this yourself. After the dialog has been constructed
- you call DoModal. If the return value is IDOK, then you can use
- the GetColor member function to retrieve the color the user
- selected.
-
- As with all of the standard dialog classes, you are permitted
- to define a message map in your derived CColorDialog class
- customize the dialog to suite your needs. The member function
- SetCurrentColor is provided for forcing the currently selected
- color to a certain value. As with CFileDialog, a validation
- callback is provided that gives you a chance to override the OK
- selection. This validation is handled in the OnColorOK virtual
- function.
-
-
- CPrintDialog
- ============
- The CPrintDialog class provides support for a standard dialog
- that permits a user to print a document or setup the printer.
- The dialog makes use of the COMMDLG structure PRINTDLG and the
- API PrintDlg. CPrintDialog is a modal dialog derived from
- the CModalDialog class.
-
- As with CFileDialog, CPrintDialog is really two different dialogs,
- distinguished by a constructor argument. The CPrintDialog class
- can be used to respond to the Print command and/or the Print Setup
- command (both usually in the File menu.) The arguments to the
- constructor for CPrintDialog include:
-
- bPrintSetupOnly TRUE if you want only a Print Setup
- dialog, FALSE for the Print dialog
- dwFlags is a set of flags that you can use to customize
- the function and appearance of the dialog. See
- the PRINTDLG structure reference for more
- information on possible values. (defaults to
- PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS
- | PD_HIDEPRINTTOFILE | PD_NOSELECTION)
- pParentWnd is a pointer to a parent Window. This is
- used only when routing customized help
- messages (defaults to NULL.)
-
- You may use the GetDefaults member function to retrieve the
- current printer defaults. All of the helper functions described
- below will be valid after a successful return. Note that
- this member function requires no user interaction.
-
- As with other standard dialogs, you can customize the appearance
- and functionality by directly modifying the PRINTDLG structure,
- which is the m_pd member variable. After any customization
- you call DoModal, which will return IDOK or IDCANCEL as expected.
- Remember to check for extended errors if IDCANCEL is the return
- value, since there might have been a setup error. If IDOK
- is returned there are a number of functions that can be used
- to retrieve information about the selected printer. Some of
- these functions might not be valid, depending on the settings
- of dwFlags and m_pd.Flags.
-
- GetCopies returns the number of copies the user chose
- GetFromPage returns the starting page of the print job
- GetToPage returns the ending page of the print jon
- GetDevMode returns a pointer to the device mode
- GetDriverName returns a string that is the driver name
- GetDeviceName returns a string that is the device name
- GetPortName returns a string that is the port name
- PrintCollate returns TRUE if the job is to be collated
- PrintAll returns TRUE if All pages selected
- PrintRange returns TRUE if the user entered a print range
- (GetFromPage and GetToPage are then valid)
- PrintSelection returns TRUE if the user wishes to print
- the current selection
- GetPrinterDC returns an HDC for the selected printer
-
- The GetPrinterDC function returns an HDC only if the bPrintSetupOnly
- constructor parameter was FALSE (i.e. the Print dialog is displayed.)
- You are responsible for calling DeleteDC. If you wish to
- use this DC as an MFC CDC object, then you can attach it to
- an object as follows:
- {
- CDC printerDC;
- CPrintDialog pd(FALSE);
- if (pd.DoModal() == IDCANCEL)
- return FALSE;
- printerDC.Attach(pd.GetPrinterDC());
- // print using printerDC
- } // falling out of scope will implicitly call CDC::DeleteDC
-
- While the Print dialog is active, it is possible for the user to
- obtain a Print Setup dialog and further customize the print job.
- MFC handles this automatically for you.
-
- You may customize the CPrintDialog object by deriving your
- own class from it and using a message map to handle messages and
- commands of your choosing. If you wish to handle the same message
- differently depending on if the Print dialog or Print Setup dialog
- is active you will need to derive an additional class, one
- for the Print dialog and one for your custom Print Setup dialog. In
- your print dialog class you will also need to override the
- AttachOnSetup member function. This function handles the creation
- of a new dialog for when the Print Setup button is clicked. The
- source code in \C700\MFC\SRC\WINDLGS.CPP provides more documentation
- on how to implement this feature.
-
-
- CFindReplaceDialog
- ==================
- The CFindReplaceDialog class is a standard modeless dialog for implementing
- a dialog that queries the user for a find/replace string pair. The
- dialog is dual purpose in that it can display either a Find dialog
- or a Find Replace dialog. This is a modeless dialog and is
- derived from the CDialog class. You are responsible for implementing
- code that does the actual search and replace, as this dialog only
- receives input from the user. The relevant parameter block
- structure is FINDREPLACE and the APIs used are FindText and
- ReplaceText.
-
- Since this dialog is modeless, it should be dynamically allocated
- using operator new. If you wish to allocate a CFindReplace dialog
- on the stack frame, you will need to derive your own CFindReplaceDialog
- and override the default behavior of the PostNcDestroy function.
- The constructor for this class takes no arguments. When your application
- needs to query the user for find/replace information the Create
- member function is called. This will create and show the modeless
- dialog. The parameters to Create are as follows:
-
- bFindDialogOnly TRUE for Find, FALSE for Find and Replace
- lpszFindWhat the default search string, such as the
- current selection
- lpszReplaceWith the default replacement string
- (defaults to NULL)
- dwFlags is a set of flags that you can use to customize
- the function and appearance of the dialog. See
- the FINDREPLACE structure reference for more
- information on possible values. (defaults to
- FR_DOWN)
- pParentWnd the parent of the dialog, this is the dialog
- that receives the special message indicating
- that a find/replace action is requested (defaults
- to the current frame window, CWinApp::m_pMainWnd)
-
- In order for the pParentWnd to be notified of find/replace requests
- you must use the Windows API ::RegisterMessage(FINDMSGSTRING). The
- return value of this function is a message number that is unique to this
- application instance. Your frame window should have a message map
- entry that handles this registered message. The following code
- fragments show how to do this for a frame window class CMyFrameWnd.
-
- class CMyFrameWnd : public CFrameWnd
- {
- // normal members
-
- protected:
- // CFindReplaceDialog helpers
- static CFindReplace* pFindReplace;
- static UINT nMsgFind;
- afx_msg LONG CmdFindHelper(UINT wParam, LONG lParam);
-
- DECLARE_MESSAGE_MAP()
- };
-
- BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
- // normal message map entries
- ON_REGISTERED_MESSAGE(nMsgFind, CmdFindHelper)
- END_MESSAGE_MAP
-
- UINT CMyFrameWnd::nMsgFind = ::RegisterMessage(FINDMSGSTRING);
- CFindReplace* CMyFrameWnd::pFindReplace = NULL;
-
- Note the use of a static member that is the current CFindReplaceDialog
- object. When the user first executes the Find command, a dialog will
- be created and that object will be used until the Close command on
- the system menu is executed or the user clicks CANCEL.
-
- Within the CmdFindHelper you will interpret the intentions of the
- user and do the work for find/replace. In order to assist you, there
- are a number of helper functions available:
-
- GetFindString returns the current find string
- SearchDown TRUE of the user wishes to search down
- the document
- FindNext TRUE if the user clicked the Find Next
- button
- MatchCase TRUE if the user wishes to match case
- of text exactly
- MatchWholeWord TRUE if the user wishes to match entire
- words only
- GetReplaceString returns the current replace string for
- a replace dialog
- ReplaceCurrent TRUE is the user requested that the current
- word be replaced in a replace dialog
- ReplaceAll TRUE if the user wishes all occurrences
- to be replaced
- IsTerminating TRUE is the dialog is terminating (the
- current m_hWnd is no longer valid when this
- function returns TRUE)
- GetNotifier return the CFindReplaceDialog structure
- (valid only in the CmdFindHandler callback
- function)
-
- The CmdFindHandler upon being called will first use the static
- member function of CFindReplaceDialog, GetNotifier, to convert
- the lParam into a CFindReplaceDialog object pointer, which will
- then be used to call member functions and extract dialog information.
- If you derived your own CFindReplaceDialog, you will need to
- provide a typesafe castdown static member function to safely convert
- the lParam to your own derived CFileDialog.
-
- Normally the CmdFindHandler will then do a check to see if the
- dialog is being terminated (using IsTerminating) and if this is
- TRUE you will cleanup (delete the current pFindReplace dialog and
- set the member variable to NULL) and possibly store away the
- final find/replace text to be used in the initialization of the
- next dialog.
-
- Although this dialog is a modeless dialog, as with other
- CDialog derived modeless dialogs MFC automatically
- handles the translation dialog messages and routes them to
- your dialog's message map. Thus you are free to customize your
- CFindReplaceDialog by deriving and supplying a message map with
- the necessary handlers.
-
-
- Advanced Usage Notes
- ====================
- Many of these dialogs permit the use of strings to customize
- the appearance or functionality of the dialog. Whenever a
- string is used, it is best to use a STRINGTABLE resource
- rather than embedding the string in your code. The CString::LoadString
- API can assist you in loading a string from a resource file.
- Similarly, if the string is read-only, you could place it in
- a code segment (use the MFC helper macro BASED_CODE.)
-
- The standard COMMDLG functions all permit the user to add special
- "hook" functions in order to customize the dialog box appearance and
- functionality. With MFC you should not use these special
- hook procedures, but you should use a derived class and a message
- just as you would for any other standard Windows dialog. If you
- require the use of the hook function, be sure to save the MFC
- hook function and call it if you do not handle a message, just
- as when dynamically subclassing a Windows window.
-
- As with other short-lived objects, dialogs that derive from
- the CModalDialog class are best allocated on the stack frame.
- The CFindReplaceDialog class is designed to be heap allocated
- (via operator new) since it is a long-lived object.
-
- All of these dialog classes have a parent window pointer as
- a constructor parameter. The classes will all use the current
- frame window (CWinApp::m_pMainWnd) as the parent if you
- specify NULL as the pParentWnd parameter (the default.) If
- you are spawning a standard dialog from another dialog, it
- you must pass the current dialog as the the parent pointer
- (the 'this' pointer in the command handler that spawns the
- dialog. If you do not, the two dialogs will have sibling
- relationship rather than a parent/child relationship.
-
- COMMDLG functions require significant stack space, so be
- sure to have at least 16K of stack space available (use the
- .DEF file to change the default.)
-