DOCUMENT:Q117563 07-MAY-2001 [visualc] TITLE :HOWTO: How to Trap WM_KEYDOWN Messages in a CDialog PRODUCT :Microsoft C Compiler PROD/VER:winnt:2.0,2.1,4.0 OPER/SYS: KEYWORDS:kbDlg kbHook kbKeyIn kbMFC kbVC100 kbVC150 kbVC200 kbVC400 kbArchitecture ====================================================================== ------------------------------------------------------------------------------- The information in this article applies to: - The Microsoft Foundation Classes (MFC), used with: - Microsoft Visual C++ for Windows, 16-bit edition, versions 1.0, 1.5, 1.51, 1.52 - Microsoft Visual C++, 32-bit Editions, versions 2.0, 2.1, 4.0 - Microsoft Visual C++ 32-bit Edition, versions 2.0, 2.1, 4.0 ------------------------------------------------------------------------------- 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. 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: 1. 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 public: HWND m_hwndDialog; SCRIBBLE.CPP m_hwndDialog = NULL; NOTE: Because this message filter applies to the entire application, there may be a performance hit when you use this method. 2. 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. 3. 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 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; } 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) If this method is unacceptable because of the application-wide nature of the message filter, please see the following article in the Microsoft Knowledge Base: Q72219 Context-Sensitive Help in a Dialog Box Through F1 This article explains how to set a hook function for a specific dialog and how to remove the hook after the dialog box has terminated. That method requires more Windows programming knowledge. Additional query words: kbinf 1.00 1.50 2.00 2.10 2.50 3.00 3.10 4.00 key keystroke ====================================================================== Keywords : kbDlg kbHook kbKeyIn kbMFC kbVC100 kbVC150 kbVC200 kbVC400 kbArchitecture Technology : kbAudDeveloper kbMFC Version : winnt:2.0,2.1,4.0 Issue type : kbhowto ============================================================================= THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY. Copyright Microsoft Corporation 2001.