Login


Implement Accelerators in an MFC Dialog Box

By Jonathan Wood on 12/2/2010 (Updated on 12/12/2010)
Language: C++
Technology: MFC
Platform: Windows
License: CPOL
Views: 5,106
Frameworks & Libraries » MFC » Dialog Boxes » Implement Accelerators in an MFC Dialog Box

Demo Program Screenshot

Download Source Code Download Source Code

Introduction

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 an application 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 a dialog-based application.

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.

Implementing Dialog Accelerators

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.

Listing 1: Add variable to main application class

HACCEL m_hAccelTable;

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.

Listing 2: Initialize variable in InitInstance()

BOOL CMyApp::InitInstance()
{
  // ...
  m_hAccelTable = LoadAccelerators(AfxGetInstanceHandle(),
    MAKEINTRESOURCE(IDR_ACCELERATOR1));
  // ...
}

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.

Listing 3: Override ProcessMessageFilter()

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);
}

Conclusion

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).

End-User License

Use of this article and any related source code or other files is governed by the terms and conditions of The Code Project Open License.

Author Information

Jonathan Wood

I'm a software and website developer working out of the greater Salt Lake City area of Utah. I've developed many websites including Black Belt Coder, Trail Calendar, and others.

I hike each week with my dogs Suki and Sasha. You can see my hiking blog at Hiking Salt Lake.