回 帖 发 新 帖 刷新版面

主题:[讨论]求助 关于对话框的响应WM_KEYDOWN消息

在对话框程序中,我们经常是利用对话框上的子控件进行命令响应来处理一些事件。如果我们想要让对话框(子控件的父窗口)类来响应我们的按键消息,我们可以通过ClassWizard对WM_KEYDOWN消息进行响应,当程序运行后,我们按下键盘上的按键,但对话框不会有任何的反应。这是因为在对话框程序中,某些特定的消息,例如按键消息,它们被Windows内部的对话框过程处理了(即在基类中完成了处理,有兴趣的读者可以查看MFC的源代码),或者被发送给子控件进行处理,所以我们在对话框类中就捕获不到按键的消息了。 

既然我们知道了这个处理的过程,我们就可以找到底层处理按键消息的函数,然后在子类中重载它,就可以在对话框程序中处理按键消息了。在MFC中,是利用BOOL ProcessMessageFilter(int code, LPMSG lpMsg)这个虚函数来过滤或响应菜单和对话框的特定Windows消息。下面我们通过程序给大家演示基于对话框的应用程序对WM_KEYDOWN消息的捕获。 

第一步:新建一个工程,选择MFC AppWizard (exe),工程名为WinSun,点击ok,进入下一步,选择Dialog based,点击Finish。 

第二步:在CWinSunApp类上点击右键,选择Add Member Varialbe,增加一个类型为HWND,变量名m_hwndDlg的public的变量。代码如下: 

WinSun.h 

class CWinSunApp : public CWinApp 



public: 

      HWND m_hwndDlg; 

      CWinSunApp(); 



// Overrides 

      // ClassWizard generated virtual function overrides 

      //{{AFX_VIRTUAL(CWinSunApp) 

      public: 

      virtual BOOL InitInstance(); 

      //}}AFX_VIRTUAL 



// Implementation 



      //{{AFX_MSG(CWinSunApp) 

              // NOTE - the ClassWizard will add and remove member functions here. 

              //    DO NOT EDIT what you see in these blocks of generated code ! 

      //}}AFX_MSG 

      DECLARE_MESSAGE_MAP() 

}; 



第三步:在WinSun.cpp(CWinSunApp类)文件中的InitInstance()函数中添加如下代码: 

WinSun.cpp 

BOOL CWinSunApp::InitInstance() 



      AfxEnableControlContainer(); 



      // Standard initialization 

      // If you are not using these features and wish to reduce the size 

      //  of your final executable, you should remove from the following 

      //  the specific initialization routines you do not need. 



#ifdef _AFXDLL 

      Enable3dControls();                    // Call this when using MFC in a shared DLL 

#else 

      Enable3dControlsStatic();      // Call this when linking to MFC statically 

#endif 



      CWinSunDlg dlg; 

      m_pMainWnd = &dlg; 

      int nResponse = dlg.DoModal(); 

      if (nResponse == IDOK) 

      { 

              // TODO: Place code here to handle when the dialog is 

              //  dismissed with OK 

      } 

      else if (nResponse == IDCANCEL) 

      { 

              // TODO: Place code here to handle when the dialog is 

              //  dismissed with Cancel 

      } 



      // Since the dialog has been closed, return FALSE so that we exit the 

      //  application, rather than start the application's message pump. 

      m_hwndDlg=NULL; 

      return FALSE; 





第四步:在CWinSunApp类上点击右键,选择Add Virtual Function,在左边一栏里,选择ProcessMessageFilter,在右边按钮上选择Add and Edit,然后加入以下代码: 

WinSun.cpp 

BOOL CWinSunApp::ProcessMessageFilter(int code, LPMSG lpMsg) 



      // TODO: Add your specialized code here and/or call the base class 

      if(m_hwndDlg!=NULL) 

      { 

              //判断消息,如果消息是从对话框发出的或者其子控件发出的,我们就进行处理。sunxin 

              if((lpMsg->hwnd==m_hwndDlg) || ::IsChild(m_hwndDlg,lpMsg->hwnd)) 

              { 

                    //如果消息是WM_KEYDOWN,我们就弹出一个消息框。sunxin 

                    if(lpMsg->message==WM_KEYDOWN) 

                    { 

                            AfxMessageBox("捕获WM_KEYDOWN消息成功!"); 

                    } 

              } 

      } 

      return CWinApp::ProcessMessageFilter(code, lpMsg); 





第五步:在WinSunDlg.cpp(CWinSunDlg类)中的OnInitialDialog()函数中加入以下代码: 

WinSunDlg.cpp 

BOOL CWinSunDlg::OnInitDialog() 



      CDialog::OnInitDialog(); 



      // Add "About..." menu item to system menu. 



      // IDM_ABOUTBOX must be in the system command range. 

      ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); 

      ASSERT(IDM_ABOUTBOX < 0xF000); 



      CMenu* pSysMenu = GetSystemMenu(FALSE); 

      if (pSysMenu != NULL) 

      { 

              CString strAboutMenu; 

              strAboutMenu.LoadString(IDS_ABOUTBOX); 

              if (!strAboutMenu.IsEmpty()) 

              { 

                    pSysMenu->AppendMenu(MF_SEPARATOR); 

                    pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); 

              } 

      } 



      // Set the icon for this dialog.  The framework does this automatically 

      //  when the application's main window is not a dialog 

      SetIcon(m_hIcon, TRUE);                  // Set big icon 

      SetIcon(m_hIcon, FALSE);          // Set small icon 

      

      // TODO: Add extra initialization here 

//将对话框的句柄传递到CWinSunApp类中。sunxin 

      ((CWinSunApp*)AfxGetApp())->m_hwndDlg=m_hWnd; 
      return TRUE;  // return TRUE  unless you set the focus to a control 





第六步:在对话框窗口销毁后,将CWinSunApp类中的变量m_hwndDlg置为NULL,为此我们在CWinSunDlg类上点击右键,选择Add Windows Message Handler,在左边一栏中选择WM_DESTROY,在右边按钮上选择Add and Edit,然后加入以下代码: 

WinSunDlg.cpp 

void CWinSunDlg::OnDestroy() 



      CDialog::OnDestroy(); 

      

      // TODO: Add your message handler code here 

      ((CWinSunApp*)AfxGetApp())->m_hwndDlg=NULL; 


至此,我们的工作就做完了,现在我们可以按Ctrl+F5运行程序,看到我们想要的结果。 


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/chinawash/archive/2006/10/28/1354322.aspx 


麻烦问下 
1: 上面这篇文章里面 m_hwndDlg这个变量 先在全局APP里面定义了  然后在初始化实例里面为什么要把他赋值为NULL  我的理解是在模态窗口销毁的时候才能运行m_hwndDlg=NULL;这条语句 那么为什么还要这样赋值? 

2:在函数ProcessMessageFilter里面 他首先判断      if(m_hwndDlg!=NULL)  问题是这个时候的变量m_hwndDlg是什么时候被赋值的? 但是从下面的代码看出是系统得到确定的按键消息后和m_hwndDlg做比较 为什么这里要用这个HWND的窗口句柄类型做判断? 对于这个问题 我认为它是在判断这个消息是从哪个窗口发出来的对吧? 

未必只要在WinsunApp.h这个头里面定义一个HWND句柄 他就表示这个窗口的句柄了么? 
我用的VC6

回复列表 (共2个回复)

沙发

你好.我是全职网赚工作者.
如果你有时间有电脑.
想在网络上创业.请联系我..
项目绝对真实.详情QQ空间资料
加盟请联系摩客元亨 QQ908889846
2010年,中国网民突破了4亿,
网络游戏玩家超过了3亿,
互联网即将进入全民网游的时代

板凳

寻找中国的最优秀的网商领袖精英 淘宝商盟元亨 qq: 908889846 
当今世界正经历着全球经济一体化的大潮,中国本土企业也因此面临着前所未有的机遇与挑战。
在这场洗礼中,哪些互联网平台有能力成为世界级的电子商务平台?网商精英要怎样做,才能最终成长为世界级网商精英领袖?
淘宝商盟平台震撼登场,携手淘宝30万商家联盟购物商城。
平台刚刚启动,互联网的网商精英请咨询qq: 908889846 
占领市场第一先机,合力打造网商系统!
淘宝商盟官网   www.taobaosm.com
 http://blog.sina.com.cn/tbsm8
淘宝商盟奖励制度

我来回复

您尚未登录,请登录后再回复。点此登录或注册