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
.
Author Information
Jonathan Wood
I'm a software/website developer working out of the greater Salt Lake City area in Utah. I've developed many websites including Black Belt Coder, Insider Articles, and others.