Microsoft KB Archive/117563

= HOWTO: How to Trap WM_KEYDOWN Messages in a CDialog =

Article ID: 117563

Article Last Modified on 1/18/2007

-

APPLIES TO

 Microsoft Foundation Class Library 4.2, when used with:  Microsoft Visual C++ 1.0 Professional Edition

 Microsoft Visual C++ 1.5 Professional Edition

 Microsoft Visual C++ 1.51

 Microsoft Visual C++ 1.52 Professional Edition</li></ul>

 Microsoft Visual C++ 2.0 Professional Edition</li></ul>

 Microsoft Visual C++ 2.1</li></ul>

 Microsoft Visual C++ 4.0 Standard Edition</li></ul>

 Microsoft Visual C++ 5.0 Learning Edition</li></ul>

 Microsoft Visual C++ 2.0 Professional Edition</li></ul>

 Microsoft Visual C++ 2.1</li></ul>

 Microsoft Visual C++ 4.0 Professional Edition</li></ul> </li></ul>

-

<div class="notice_section">

This article was previously published under Q117563

<div class="summary_section">

SUMMARY
Certain Windows messages are difficult to trap in a dialog box because they are either processed by the Windows internal dialog procedure or sent to the control instead of the dialog box. There are several ways to do this, but they usually involve subclassing all the controls in the dialog box or using a Windows hook function. The method described in this article uses the predefined overridable MFC hook function ProcessMessageFilter to capture these messages. The idea is to override the MFC preinstalled hook function, ProcessMessageFilter, to trap the messages before they get to the dialog box.

<div class="moreinformation_section">

MORE INFORMATION
The following steps are the required to implement the hook function. The SCRIBBLE sample was used as the base for the steps. In Visual C++ 32-bit Edition, version 4.0, use SCRIBBLE sample STEP3.

In this example, the steps outlined below trap WM_KEYDOWN for a specific dialog box:

<ol>  Add a member variable to your CWinApp-derived class to hold the handle to the dialog box for which you want to trap the messages. You need to know the handle because ProcessMessageFilter is receiving messages for the entire application, while you only want a small selection of those messages: SCRIBBLE.H

<Inside CScribbleApp class>

public: HWND m_hwndDialog;

SCRIBBLE.CPP

<Inside CScribbleApp::InitInstance>

m_hwndDialog = NULL; NOTE: Because this message filter applies to the entire application, there may be a performance hit when you use this method. </li>  Override CWinApp::ProcessMessageFilter in your CWinApp-derived class. CWinApp::ProcessMessageFilter is a virtual function of CWinApp, so all you need to do is put a declaration in the header file and an implementation in the source file. SCRIBBLE.H

public: virtual BOOL ProcessMessageFilter(int code, LPMSG lpMsg);

SCRIBBLE.CPP

BOOL CScribbleApp::ProcessMessageFilter(int code, LPMSG lpMsg) {             // Check to make sure CPenWidthsDlg is up           if (m_hwndDialog != NULL) {            if ((lpMsg->hwnd == m_hwndDialog) ||                 ::IsChild(m_hwndDialog, lpMsg->hwnd)) // Use ::IsChild to get messages that may be going // to the dialog's controls. In the case of               // WM_KEYDOWN this is required. {                 if (lpMsg->message == WM_KEYDOWN) TRACE("Got WM_KEYDOWN\n"); }             }           // Default processing of the message. return CWinApp::ProcessMessageFilter(code, lpMsg); } For more information on overriding ProcessMessageFilter, please see the MFC online Help. </li> <li> Add initialization code for the dialog handle member variable in our OnInitDialog for the desired dialog box. You also have to add exit code to reset the member variable after the dialog box closes: PENDLG.H

protected: virtual BOOL OnInitDialog; afx_msg void OnDestroy;

PENDLG.CPP

<Add to Message Map> ON_WM_DESTROY

BOOL CPenWidthsDlg::OnInitDialog {          CDialog::OnInitDialog;

// Use AfxGetApp to get pointer to CWinApp-derived // object; then cast the pointer to our type and assign ((CScribbleApp *)AfxGetApp)->m_hwndDialog = m_hWnd;

return TRUE; // Return TRUE // unless you set the focus to a control. }

void CPenWidthsDlg::OnDestroy {          CDialog::OnDestroy;

// Use AfxGetApp to get pointer to CWinApp-derived // object; then cast the pointer to our type and assign ((CScribbleApp *)AfxGetApp)->m_hwndDialog = NULL;

}                       </li></ol>

Once these steps are completed, you can trap any message intended for the CPenWidthsDlg or any of its children (such as edit controls, combo boxes, and radio buttons)

Additional query words: kbinf 1.00 1.50 2.00 2.10 2.50 3.00 3.10 4.00 key keystroke

Keywords: kbhowto kbkeyin kbhook kbarchitecture kbdlg KB117563

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.