Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Implement Accelerators in a Dialog-Based Application

0.00/5 (No votes)
4 Jul 2012 1  
Getting accelerators to work in a dialog box.

One of the options you have when creating an MFC application is to make your application dialog-based. This is one of the options in the MFC Wizards.

Dialog-based applications are simply applications where the main window is a dialog box. Applications that need to display a bunch of controls in the main window are considerably easier to implement as dialog-based applications.

In addition, you can also add a menu to your dialog box, which can complete a sophisticated dialog-based application. A menu can be added by simple choosing the menu resource ID in the Properties window for the dialog box. But if your menu has accelerators (hotkeys), you’ll notice that they don’t work. In this article, I’ll describe getting accelerators to work in a dialog box.

The discussion below assumes you have created a dialog box with a menu, that you’ve also created an accelerator resource with hotkeys for one or more commands in your dialog box menu, and that you’ve defined handlers for those commands.

In your main application class (not the dialog box class), define the following member variable:

HACCEL m_hAccelTable;
Listing 1: Add variable to main application class.

Next, initialize this variable in your main application class’s InitInstance() method. You may want to initialize it after the basic MFC initialization code, but be sure to initialize it before the main dialog box is displayed. Again, this is in your main application class and not in your dialog box class.

BOOL CMyApp::InitInstance()
{
 // ...

 m_hAccelTable = LoadAccelerators(AfxGetInstanceHandle(),
    MAKEINTRESOURCE(IDR_ACCELERATOR1));

 // ...
}
Listing 2: Initialize variable in InitInstance().

Note that this code assumes the ID of your accelerator is IDR_ACCELERATOR1. You’ll need to change it if you are using a different resource ID.

Next, override ProcessMessageFilter in your main application class. Again, this is in your main application class and not in your dialog box class.

BOOL CMyApp::ProcessMessageFilter(int code, LPMSG lpMsg)
{
 if (code >= 0 && m_pMainWnd && m_hAccelTable)
   {
   if (::TranslateAccelerator(m_pMainWnd->m_hWnd, m_hAccelTable, lpMsg))
      return TRUE;
  }
  return CWinApp::ProcessMessageFilter(code, lpMsg);
}
Listing 3: Override ProcessMessageFilter().

And that’s all there is to it. Assuming you have the menu and accelerator resources implemented and associated with your dialog box, and you have handlers for the commands, the accelerators should now work.

I’m not sure why this change is even necessary and couldn’t easily find out. At first glance, it sure seems like this trivial amount of code should be implemented in the base MFC classes. But this approach is simple, and should work for any dialog box in your application (that includes a menu and accelerator resource).

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here