|
|
1.1 ! root 1: ! 2: Microsoft Foundation Classes Microsoft Corporation ! 3: Technical Notes ! 4: ! 5: #13 : Using the standard dialog classes ! 6: ! 7: ! 8: This note describes the use of the standard dialog classes provided ! 9: with MFC. The classes are CFileDialog, CFontDialog, CColorDialog, ! 10: CPrintDialog, and CFindReplaceDialog. They provide standard user interface ! 11: objects for your application. The class declarations for these ! 12: classes can be found in the source file \C700\MFC\INCLUDE\AFXDLGS.H. ! 13: ============================================================================= ! 14: ! 15: ! 16: Requirements ! 17: ============ ! 18: You may use these classes for any MFC application. Although these ! 19: classes use the Windows 3.1 COMMDLG functions, they do not require ! 20: Windows 3.1 to run. You must redistribute COMMDLG.DLL with your ! 21: application and install the DLL in the user's Windows 3.0 system directory. ! 22: When building an application that uses these classes, you must ! 23: link with the library COMMDLG.LIB, which is part of the Windows SDK ! 24: installation. ! 25: ! 26: ! 27: General Use ! 28: =========== ! 29: These dialogs classes may be used in one of two ways. You can use them ! 30: "as is" and supply the necessary arguments to the constructor to ! 31: customize the dialogs to suit your needs. You might also ! 32: consider deriving from these classes and providing a specific constructor ! 33: tailored to your needs. In either case, these dialogs act ! 34: like standard MFC dialogs, since they derive from CDialog (either ! 35: directly or indirectly.) You can use message maps and customize ! 36: these dialogs even more. ! 37: ! 38: COMMDLG dialog APIs interface with the application code via ! 39: a parameter block structure. The MFC dialog classes provide ! 40: public access to this structure, which may be accessed at any ! 41: time to permit maximum customization. On the other hand, MFC ! 42: provides sensible defaults for most of the fields in the parameter ! 43: block so that you do not need to worry about them. These structures ! 44: are described in the online Windows 3.1 API reference. ! 45: ! 46: ! 47: Examples ! 48: ======== ! 49: The MULTIPAD sample application uses the CFileDialog, CFontDialog, ! 50: and CPrintDialog. The CHART application uses CFileDialog ! 51: and CPrintDialog. The MDI application uses the CColorDialog. In ! 52: addition, the OLE classes use the standard CFileDialog for ! 53: implementing standard OLE user interface objects. ! 54: ! 55: ! 56: CFileDialog ! 57: =========== ! 58: The CFileDialog class encapsulates the OPENFILENAME structure ! 59: and the two Windows APIs GetOpenFileName and GetSaveFileName. This ! 60: dialog box is used to obtain from a user either a new file name ! 61: or the name of an existing file to open. CFileDialog is a modal ! 62: dialog and derives from the class CModalDialog. ! 63: ! 64: To use a CFileDialog class object, create an object using the CFileDialog ! 65: constructor. The arguments to the constructor are below, note ! 66: that several have default values: ! 67: ! 68: bOpenFileDialog set to TRUE for file open dialog, FALSE for ! 69: a file save dialog ! 70: lpszDefExt is the default extension, if a user does not ! 71: include a file extension, this is ! 72: automatically appended. ! 73: lpszFileName is the initial file name (defaults to NULL) ! 74: dwFlags is a set of flags that you can supply ! 75: that allow you to customize the dialog box. ! 76: See the online Windows API reference ! 77: (OPENFILESTRUCT) for more information ! 78: (defaults to OFN_HIDEREADONLY | ! 79: OFN_OVERWRITEPROMPT) ! 80: lpszFilter is a series of pairs of strings that specify ! 81: filters the user may apply to the files. ! 82: See below (defaults to NULL) ! 83: pParentWnd is a pointer to a parent Window. This is ! 84: used only when routing customized help ! 85: messages (defaults to NULL.) ! 86: ! 87: The lpszFilter is used to display a possible list of suffixes. For ! 88: example Microsoft Excel permits users to open *.XLC and *.XLS ! 89: (and many others). The filter for Excel would look something ! 90: like the following: ! 91: ! 92: char BASED_CODE szFilter[] = ! 93: "Chart Files (*.xlc)|*.xlc|Worksheet Files (*.xlm)|*.xlm|All Files (*.*)|*.*||" ! 94: ! 95: Note the use of '|' to separate the components of the filter. Also ! 96: note that the entire filter ends with two '|'. This is the ! 97: standard MFC syntax for specifying filters. Also, note that the ! 98: entire string is a standard NULL terminated C string, though you ! 99: can always use an MFC CString object. ! 100: ! 101: Once the dialog has been constructed, you are free to modify the ! 102: public member variable m_ofn, which is an OPENFILENAME structure. ! 103: You may manually set any flags or fields that you need. When you ! 104: are ready to prompt the user call the DoModal function (this is ! 105: a virtual function derived from CModalDialog.) The user is then ! 106: prompted for a file name (either an existing file or new file, ! 107: depending on the bOpenFileDialog constructor parameter.) When ! 108: the user clicks OK, CANCEL, or selected the CLOSE option from the ! 109: dialogs System Menu, control is returned to your application. The ! 110: return value from DoModal indicates success (IDOK) or ! 111: failure (IDCANCEL.) If the return value is IDCANCEL, either the ! 112: user closed the dialog or clicked CANCEL, or there was an error ! 113: in the parameter block. If you suspect an error, you can call ! 114: the CommDlgExtendedError API to learn more about the problem. ! 115: CommDlgExtendedError function returns 0 if there was no error. ! 116: This function differs from the standard OnOK and OnCancel functions ! 117: in that it is possible to force the user to change actions, whereas ! 118: OnOK and OnCancel are notifications that you must accept. ! 119: ! 120: If the user chose a file name, then you can continue processing. ! 121: The CFileDialog class provides a number of helper functions to ! 122: retrieve information regarding the users choice: ! 123: ! 124: GetPathName retrieves the fully qualified path name of the ! 125: selected file (suitable to use with CFile) ! 126: GetFileName retrieves just the file name without an extension ! 127: GetFileExt retrieves only the file extension (without a '.') ! 128: GetFileTitle retrieves the preferred title of the file, which ! 129: should be used as the title text of the frame window ! 130: GetReadOnlyPref returns TRUE if the user checked the read-only ! 131: option. If this is TRUE, you should open the file ! 132: with read-only permissions. ! 133: ! 134: There are also several "callback" functions that you may respond ! 135: to in your derived CFileDialog class. You do not need message map ! 136: entries for these, since they are standard virtual functions. ! 137: ! 138: OnShareViolation this function is called when a network ! 139: sharing violation occurs while processing ! 140: the dialog. See OPENFILENAME in the Windows ! 141: API for more information. ! 142: OnLBSelChangeNotify this function is called whenever the ! 143: user changes the selection(s) in the file ! 144: list. You can use this message if you ! 145: need to do extra work when a file is ! 146: a potential selection, such as calculating ! 147: disk space required, or displaying ! 148: file access rights. ! 149: OnFileNameOK this function is called when the user ! 150: selects OK. You can validate the file name ! 151: and determine if the user can continue. If ! 152: you return TRUE, be sure to indicate to the ! 153: user the problem with the selected file(s.) ! 154: ! 155: One other technique available to customize the CFileDialog is to ! 156: introduce a message map in a derived class and to handle messages ! 157: just as you would for any other dialog. For example, you can modify ! 158: the dialog background color or handle the command messages for ! 159: a new control (the .RC file for the dialog is included.) ! 160: ! 161: ! 162: CFontDialog ! 163: =========== ! 164: The CFontDialog class provides support for a standard dialog ! 165: that permits a user to choose a font. The dialog makes use ! 166: of the COMMDLG structure CHOOSEFONT and the API ChooseFont. ! 167: CFontDialog is a modal dialog derived from the CModalDialog class. ! 168: ! 169: To use a CFontDialog class object, create an object using the CFontDialog ! 170: constructor. The arguments to the constructor are below, note ! 171: that several have default values: ! 172: ! 173: lplfInitial the initial settings of the dialog box (defaults ! 174: to NULL) ! 175: dwFlags is a set of flags that you can use to customize ! 176: the function and appearance of the dialog. See ! 177: the CHOOSEFONT structure reference for more ! 178: information on possible values. (defaults to ! 179: CF_EFFECTS | CF_SCREENFONTS) ! 180: hdcPrinter if supplied is a CDC for the printer for which fonts ! 181: are to be selected (defaults to NULL) ! 182: pParentWnd is a pointer to a parent Window. This is ! 183: used only when routing customized help ! 184: messages (defaults to NULL) ! 185: ! 186: As with the CFileDialog class, once the object has been constructed ! 187: you are free to modify the CHOOSEFONT structure, m_cf, in order ! 188: to customize the dialog box fully. After any further customization, ! 189: you call the member function DoModal, which will return either ! 190: IDOK or IDCANCEL. If the return value is IDCANCEL, the user clicked ! 191: on CANCEL or there was an initialization error in the dialog. You ! 192: may use the CommDlgExtendedError function to determine if there ! 193: was an initialization error. If the user selected OK the IDOK value ! 194: is returned. The CFontDialog class provides a number of helper functions ! 195: for extracting information out of the dialog: ! 196: ! 197: GetFaceName returns the face name of the font ! 198: GetStyleName returns the style name of the font ! 199: GetSize returns the point size in 1/10ths of a point ! 200: GetColor returns the color of the selected font ! 201: GetWeight returns the weight of the font ! 202: IsStrikeout returns TRUE if the strikeout effect was selected ! 203: IsUnderline returns TRUE if the underline effect was selected ! 204: IsBold returns TRUE if the weight is equal to FW_BOLD ! 205: IsItalic returns TRUE if the font is italic ! 206: ! 207: In addition, the member variable m_lf is the LOGFONT descriptor ! 208: of the font, which can be used in a CreateFontIndirect call, ! 209: or accessed directly. ! 210: ! 211: You may customize the dialog by deriving your own class from CFontDialog ! 212: and using a message map to handle any messages. You can also use ! 213: the CFontDialog::GetCurrentFont member function to determine the ! 214: currently selected font while in a message handler. ! 215: ! 216: ! 217: CColorDialog ! 218: ============ ! 219: The CColorDialog class provides support for a standard dialog ! 220: that permits a user to choose/create a color. The dialog makes use ! 221: of the COMMDLG structure CHOOSECOLOR and the API ChooseColor. ! 222: CColorDialog is a modal dialog derived from the CModalDialog class. ! 223: ! 224: CColorDialog is used just like CFontDialog. The COMMDLG structure ! 225: that is used for customizing the dialog is CHOOSECOLOR, and it ! 226: can be modified after construction of the object and before ! 227: DoModal is called. The arguments to the constructor are as ! 228: follows: ! 229: ! 230: clrInit is a COLORREF that is the initial color selection ! 231: (defaults to RGB(0,0,0)) ! 232: dwFlags is a set of flags that you can use to customize ! 233: the function and appearance of the dialog. See ! 234: the CHOOSECOLOR structure reference for more ! 235: information on possible values. (defaults to 0) ! 236: pParentWnd is a pointer to a parent Window. This is ! 237: used only when routing customized help ! 238: messages (defaults to NULL.) ! 239: ! 240: In addition, the CColorDialog permits the user to define up to 16 ! 241: custom colors. The CColorDialog saves these custom colors between ! 242: invocations of the dialog in the static member variable clrSavedCustom. ! 243: If you wish to save these colors between executions of the application, ! 244: then you must do this yourself. After the dialog has been constructed ! 245: you call DoModal. If the return value is IDOK, then you can use ! 246: the GetColor member function to retrieve the color the user ! 247: selected. ! 248: ! 249: As with all of the standard dialog classes, you are permitted ! 250: to define a message map in your derived CColorDialog class ! 251: customize the dialog to suite your needs. The member function ! 252: SetCurrentColor is provided for forcing the currently selected ! 253: color to a certain value. As with CFileDialog, a validation ! 254: callback is provided that gives you a chance to override the OK ! 255: selection. This validation is handled in the OnColorOK virtual ! 256: function. ! 257: ! 258: ! 259: CPrintDialog ! 260: ============ ! 261: The CPrintDialog class provides support for a standard dialog ! 262: that permits a user to print a document or setup the printer. ! 263: The dialog makes use of the COMMDLG structure PRINTDLG and the ! 264: API PrintDlg. CPrintDialog is a modal dialog derived from ! 265: the CModalDialog class. ! 266: ! 267: As with CFileDialog, CPrintDialog is really two different dialogs, ! 268: distinguished by a constructor argument. The CPrintDialog class ! 269: can be used to respond to the Print command and/or the Print Setup ! 270: command (both usually in the File menu.) The arguments to the ! 271: constructor for CPrintDialog include: ! 272: ! 273: bPrintSetupOnly TRUE if you want only a Print Setup ! 274: dialog, FALSE for the Print dialog ! 275: dwFlags is a set of flags that you can use to customize ! 276: the function and appearance of the dialog. See ! 277: the PRINTDLG structure reference for more ! 278: information on possible values. (defaults to ! 279: PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS ! 280: | PD_HIDEPRINTTOFILE | PD_NOSELECTION) ! 281: pParentWnd is a pointer to a parent Window. This is ! 282: used only when routing customized help ! 283: messages (defaults to NULL.) ! 284: ! 285: You may use the GetDefaults member function to retrieve the ! 286: current printer defaults. All of the helper functions described ! 287: below will be valid after a successful return. Note that ! 288: this member function requires no user interaction. ! 289: ! 290: As with other standard dialogs, you can customize the appearance ! 291: and functionality by directly modifying the PRINTDLG structure, ! 292: which is the m_pd member variable. After any customization ! 293: you call DoModal, which will return IDOK or IDCANCEL as expected. ! 294: Remember to check for extended errors if IDCANCEL is the return ! 295: value, since there might have been a setup error. If IDOK ! 296: is returned there are a number of functions that can be used ! 297: to retrieve information about the selected printer. Some of ! 298: these functions might not be valid, depending on the settings ! 299: of dwFlags and m_pd.Flags. ! 300: ! 301: GetCopies returns the number of copies the user chose ! 302: GetFromPage returns the starting page of the print job ! 303: GetToPage returns the ending page of the print jon ! 304: GetDevMode returns a pointer to the device mode ! 305: GetDriverName returns a string that is the driver name ! 306: GetDeviceName returns a string that is the device name ! 307: GetPortName returns a string that is the port name ! 308: PrintCollate returns TRUE if the job is to be collated ! 309: PrintAll returns TRUE if All pages selected ! 310: PrintRange returns TRUE if the user entered a print range ! 311: (GetFromPage and GetToPage are then valid) ! 312: PrintSelection returns TRUE if the user wishes to print ! 313: the current selection ! 314: GetPrinterDC returns an HDC for the selected printer ! 315: ! 316: The GetPrinterDC function returns an HDC only if the bPrintSetupOnly ! 317: constructor parameter was FALSE (i.e. the Print dialog is displayed.) ! 318: You are responsible for calling DeleteDC. If you wish to ! 319: use this DC as an MFC CDC object, then you can attach it to ! 320: an object as follows: ! 321: { ! 322: CDC printerDC; ! 323: CPrintDialog pd(FALSE); ! 324: if (pd.DoModal() == IDCANCEL) ! 325: return FALSE; ! 326: printerDC.Attach(pd.GetPrinterDC()); ! 327: // print using printerDC ! 328: } // falling out of scope will implicitly call CDC::DeleteDC ! 329: ! 330: While the Print dialog is active, it is possible for the user to ! 331: obtain a Print Setup dialog and further customize the print job. ! 332: MFC handles this automatically for you. ! 333: ! 334: You may customize the CPrintDialog object by deriving your ! 335: own class from it and using a message map to handle messages and ! 336: commands of your choosing. If you wish to handle the same message ! 337: differently depending on if the Print dialog or Print Setup dialog ! 338: is active you will need to derive an additional class, one ! 339: for the Print dialog and one for your custom Print Setup dialog. In ! 340: your print dialog class you will also need to override the ! 341: AttachOnSetup member function. This function handles the creation ! 342: of a new dialog for when the Print Setup button is clicked. The ! 343: source code in \C700\MFC\SRC\WINDLGS.CPP provides more documentation ! 344: on how to implement this feature. ! 345: ! 346: ! 347: CFindReplaceDialog ! 348: ================== ! 349: The CFindReplaceDialog class is a standard modeless dialog for implementing ! 350: a dialog that queries the user for a find/replace string pair. The ! 351: dialog is dual purpose in that it can display either a Find dialog ! 352: or a Find Replace dialog. This is a modeless dialog and is ! 353: derived from the CDialog class. You are responsible for implementing ! 354: code that does the actual search and replace, as this dialog only ! 355: receives input from the user. The relevant parameter block ! 356: structure is FINDREPLACE and the APIs used are FindText and ! 357: ReplaceText. ! 358: ! 359: Since this dialog is modeless, it should be dynamically allocated ! 360: using operator new. If you wish to allocate a CFindReplace dialog ! 361: on the stack frame, you will need to derive your own CFindReplaceDialog ! 362: and override the default behavior of the PostNcDestroy function. ! 363: The constructor for this class takes no arguments. When your application ! 364: needs to query the user for find/replace information the Create ! 365: member function is called. This will create and show the modeless ! 366: dialog. The parameters to Create are as follows: ! 367: ! 368: bFindDialogOnly TRUE for Find, FALSE for Find and Replace ! 369: lpszFindWhat the default search string, such as the ! 370: current selection ! 371: lpszReplaceWith the default replacement string ! 372: (defaults to NULL) ! 373: dwFlags is a set of flags that you can use to customize ! 374: the function and appearance of the dialog. See ! 375: the FINDREPLACE structure reference for more ! 376: information on possible values. (defaults to ! 377: FR_DOWN) ! 378: pParentWnd the parent of the dialog, this is the dialog ! 379: that receives the special message indicating ! 380: that a find/replace action is requested (defaults ! 381: to the current frame window, CWinApp::m_pMainWnd) ! 382: ! 383: In order for the pParentWnd to be notified of find/replace requests ! 384: you must use the Windows API ::RegisterMessage(FINDMSGSTRING). The ! 385: return value of this function is a message number that is unique to this ! 386: application instance. Your frame window should have a message map ! 387: entry that handles this registered message. The following code ! 388: fragments show how to do this for a frame window class CMyFrameWnd. ! 389: ! 390: class CMyFrameWnd : public CFrameWnd ! 391: { ! 392: // normal members ! 393: ! 394: protected: ! 395: // CFindReplaceDialog helpers ! 396: static CFindReplace* pFindReplace; ! 397: static UINT nMsgFind; ! 398: afx_msg LONG CmdFindHelper(UINT wParam, LONG lParam); ! 399: ! 400: DECLARE_MESSAGE_MAP() ! 401: }; ! 402: ! 403: BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd) ! 404: // normal message map entries ! 405: ON_REGISTERED_MESSAGE(nMsgFind, CmdFindHelper) ! 406: END_MESSAGE_MAP ! 407: ! 408: UINT CMyFrameWnd::nMsgFind = ::RegisterMessage(FINDMSGSTRING); ! 409: CFindReplace* CMyFrameWnd::pFindReplace = NULL; ! 410: ! 411: Note the use of a static member that is the current CFindReplaceDialog ! 412: object. When the user first executes the Find command, a dialog will ! 413: be created and that object will be used until the Close command on ! 414: the system menu is executed or the user clicks CANCEL. ! 415: ! 416: Within the CmdFindHelper you will interpret the intentions of the ! 417: user and do the work for find/replace. In order to assist you, there ! 418: are a number of helper functions available: ! 419: ! 420: GetFindString returns the current find string ! 421: SearchDown TRUE of the user wishes to search down ! 422: the document ! 423: FindNext TRUE if the user clicked the Find Next ! 424: button ! 425: MatchCase TRUE if the user wishes to match case ! 426: of text exactly ! 427: MatchWholeWord TRUE if the user wishes to match entire ! 428: words only ! 429: GetReplaceString returns the current replace string for ! 430: a replace dialog ! 431: ReplaceCurrent TRUE is the user requested that the current ! 432: word be replaced in a replace dialog ! 433: ReplaceAll TRUE if the user wishes all occurrences ! 434: to be replaced ! 435: IsTerminating TRUE is the dialog is terminating (the ! 436: current m_hWnd is no longer valid when this ! 437: function returns TRUE) ! 438: GetNotifier return the CFindReplaceDialog structure ! 439: (valid only in the CmdFindHandler callback ! 440: function) ! 441: ! 442: The CmdFindHandler upon being called will first use the static ! 443: member function of CFindReplaceDialog, GetNotifier, to convert ! 444: the lParam into a CFindReplaceDialog object pointer, which will ! 445: then be used to call member functions and extract dialog information. ! 446: If you derived your own CFindReplaceDialog, you will need to ! 447: provide a typesafe castdown static member function to safely convert ! 448: the lParam to your own derived CFileDialog. ! 449: ! 450: Normally the CmdFindHandler will then do a check to see if the ! 451: dialog is being terminated (using IsTerminating) and if this is ! 452: TRUE you will cleanup (delete the current pFindReplace dialog and ! 453: set the member variable to NULL) and possibly store away the ! 454: final find/replace text to be used in the initialization of the ! 455: next dialog. ! 456: ! 457: Although this dialog is a modeless dialog, as with other ! 458: CDialog derived modeless dialogs MFC automatically ! 459: handles the translation dialog messages and routes them to ! 460: your dialog's message map. Thus you are free to customize your ! 461: CFindReplaceDialog by deriving and supplying a message map with ! 462: the necessary handlers. ! 463: ! 464: ! 465: Advanced Usage Notes ! 466: ==================== ! 467: Many of these dialogs permit the use of strings to customize ! 468: the appearance or functionality of the dialog. Whenever a ! 469: string is used, it is best to use a STRINGTABLE resource ! 470: rather than embedding the string in your code. The CString::LoadString ! 471: API can assist you in loading a string from a resource file. ! 472: Similarly, if the string is read-only, you could place it in ! 473: a code segment (use the MFC helper macro BASED_CODE.) ! 474: ! 475: The standard COMMDLG functions all permit the user to add special ! 476: "hook" functions in order to customize the dialog box appearance and ! 477: functionality. With MFC you should not use these special ! 478: hook procedures, but you should use a derived class and a message ! 479: just as you would for any other standard Windows dialog. If you ! 480: require the use of the hook function, be sure to save the MFC ! 481: hook function and call it if you do not handle a message, just ! 482: as when dynamically subclassing a Windows window. ! 483: ! 484: As with other short-lived objects, dialogs that derive from ! 485: the CModalDialog class are best allocated on the stack frame. ! 486: The CFindReplaceDialog class is designed to be heap allocated ! 487: (via operator new) since it is a long-lived object. ! 488: ! 489: All of these dialog classes have a parent window pointer as ! 490: a constructor parameter. The classes will all use the current ! 491: frame window (CWinApp::m_pMainWnd) as the parent if you ! 492: specify NULL as the pParentWnd parameter (the default.) If ! 493: you are spawning a standard dialog from another dialog, it ! 494: you must pass the current dialog as the the parent pointer ! 495: (the 'this' pointer in the command handler that spawns the ! 496: dialog. If you do not, the two dialogs will have sibling ! 497: relationship rather than a parent/child relationship. ! 498: ! 499: COMMDLG functions require significant stack space, so be ! 500: sure to have at least 16K of stack space available (use the ! 501: .DEF file to change the default.)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.