HOWTO: Using Accelerator Keys with Modal Dialog Box Main Window

ID: Q100770


The information in this article applies to:
  • The Microsoft Foundation Classes (MFC), used with:
    • Microsoft Visual C++ for Windows
    • Microsoft Visual C++, 32-bit Editions, versions 2.0, 2.1, 4.0, 5.0, 6.0


SUMMARY

The TRACER sample application, provided with the Microsoft Foundation Class Library, uses a modal dialog box as its main window. Many applications that use this technique also include a main menu on the dialog box (the TRACER sample does not use a menu). Typically, one or more of the menu items has a keyboard accelerator associated with it. The text below details the steps required to add a menu and keyboard accelerators to the TRACER sample.


MORE INFORMATION

A typical application, developed for the Windows operating system using C and the Microsoft Windows Software Development Kit (SDK), that uses keyboard accelerators, calls the TranslateAccelerator() function in its main message loop. However, when you use a modal dialog box as the main window, the application does not have a main message loop; instead, the application uses the dialog manager message loop (built into Windows) to translate and dispatch messages. Of course, because this message loop is not designed to process accelerators, it does not call the TranslateAccelerator() function.

To process accelerator keys in a modal dialog box, you must override the CWinApp::ProcessMessageFilter() function. The framework calls ProcessMessageFilter() before it processes a message.

Perform the following steps to modify the TRACER sample to correctly process accelerator keys:

  1. Load the TRACER project into Visual C++.


  2. For all versions of 16-bit Visual C++, and Visual C++ 32-bit Editions through version 2.2, start App Studio.

    For Visual C++ 4.0 and later, select the Resource View in the Project Workspace window.


  3. Edit the dialog box resource and specify the "thin" border style. This step is required for a dialog box that contains a menu.


  4. Create a new menu resource that contains a top level entry "&File" and a menu item "&Exit\tCTRL+E"(CTRL+X is usually associated with cutting text, so CTRL+E was used instead).


  5. Associate the menu with the dialog box by entering the menu ID in the dialog resource properties edit control.


  6. Select the "&Exit\tCTRL+E" menu item and click the ClassWizard button on the toolbar.


  7. In the Add Class dialog box, choose Select Class. Then choose CPromptDlg and click OK. Visual C++ 4.0 recognizes that the menu resource is not associated with any object and prompts you to associate it with the CPromptDlg class.


  8. In the ClassWizard dialog box, select the menu ID associated with the Exit menu, ID_FILE_EXIT, and the COMMAND message. Then choose Add Function.


  9. The Add Member Function dialog box proposes a name for the function which you can edit if desired. Click OK.


  10. Click Edit Code. Insert the following line into the function:
    
    PostMessage(WM_COMMAND, IDOK, 0L); 
    This gives the same effect as clicking OK when the user chooses Exit from the File menu. Clicking OK closes TRACER.


  11. Create a new accelerator resource and associate the CTRL+E key combination with ID_FILE_EXIT.


  12. Save the resources and close App Studio.


  13. Edit the TRACER.CPP file to declare the following variables after the #include statements:
    
    HWND    ghDlg;          // Handle to main dialog box
          HACCEL  ghAccelTable;   // Handle to accelerator table 


  14. In ClassWizard, choose the CPromptDlg and the WM_INITDIALOG message and add a function. With Visual C++ 4.0, choose the CPromptDlg class, the CPromptDlg Object ID, the WM_INITDIALOG message, and Add Function. Note that there are now two OnInitDialog() functions, one for Macintosh, surrounded by #ifdef _MAC/#endif directives, and the one just added.


  15. Edit the function added above to include the following line of code:
    
    ghDlg = m_hWnd; 
    In Visual C++ 4.0, be sure to edit the newly added function, not the existing, Machintosh-specific one:
    
    ghDlg = m_hWnd; 


  16. Edit CTraceApp::InitInstance() in the Tracer.cpp file to add the following line immediately after the call to SetDialogBkColor() or, as in Visual C++ 4.0, after the declaration of dlg, the CPromptDlg object:
    
    ghAccelTable = LoadAccelerators(AfxGetInstanceHandle(),
            MAKEINTRESOURCE(IDR_ACCELERATOR1)); 


  17. Edit the CTracerApp class definition to add the following line to the public section:
    
    virtual BOOL ProcessMessageFilter(int code, LPMSG lpMsg); 


  18. Add the following function after the InitInstance() function:
    
    BOOL CTracerApp::ProcessMessageFilter(int code, LPMSG lpMsg)
           {
              if (code < 0)
                 CWinApp::ProcessMessageFilter(code, lpMsg);
    
              if (ghDlg && ghAccelTable)
                 {
                 if (::TranslateAccelerator(ghDlg, ghAccelTable, lpMsg))
                    return(TRUE);
                 }
    
             return CWinApp::ProcessMessageFilter(code, lpMsg);
          } 


  19. Compile and run TRACER. It should have a menu. When you choose Exit from the File menu or press CTRL+E, the application closes, as expected.


Additional query words:

Keywords : kbui kbKeyAccel kbMenu kbMFC kbVC100 kbVC150 kbVC151 kbVC152 kbVC200 kbVC210 kbVC400 kbVC500 kbVC600 kbGrpMFCATL
Version : winnt:2.0,2.1,4.0,5.0,6.0
Platform : winnt
Issue type : kbhowto


Last Reviewed: November 25, 1999
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.