非模态对话框如何相应键盘消息?(ESC and Enter)

解决方案 »

  1.   

    HOHO 分好多哦 
    不过这个问题应该挺简单的吧BOOL CYOURFROM::PreTranslateMessage(MSG* pMsg) 
    {
    switch(pMsg->message)
    {
    case WM_KEYDOWN:
    switch (pMsg->wParam)
    {
    case VK_RETURN:
    {
       响应按下回车后所执行的内容
    }
    break;
                    case VK_ESCAPE:
                      {
       响应按下esc后所执行的内容
    }  
    }
    }
    return CDialog::PreTranslateMessage(pMsg);
    }
      

  2.   

    有点乱 整理一下 HOHO
    BOOL CYOURFROM::PreTranslateMessage(MSG* pMsg)  

       switch(pMsg->message) 
       { 
          case WM_KEYDOWN: 
             switch (pMsg->wParam) 
             { 
                case VK_RETURN: 
                   { 
                       响应按下回车后所执行的内容 
                     } 
                 break; 
                case VK_ESCAPE: 
                      { 
                          响应按下esc后所执行的内容 
                         }   
                 break;
              } 
         } 
    return CDialog::PreTranslateMessage(pMsg); 
      

  3.   

      我们要想在第一时间对对话框的按键做出响应,需要重载PreTranslateMessage,   
      以下的代码实现了在对话框中显示虚拟键值(virtual-key   code)   
      BOOL   CTestDlg::PreTranslateMessage(MSG*   pMsg)     
      {     
      if(pMsg->message   ==   WM_KEYDOWN)     
      {     
      ///或者直接调用OnKeyDown     
      CString   strwParam;     
      strwParam.Format("%d   ",pMsg->wParam);     
      CDC*   pDC   =   GetDC();     
      pDC->TextOut(10,10,strwParam);     
      ReleaseDC(pDC);     
      }     
      return   CDialog::PreTranslateMessage(pMsg);     
      }   
        
      此方法也适用于FORMVIEW或其它控件中对键盘按键的响应,以下的代码来自MSDN,   
      实现了当按下上下左右方向键时调用OnKeyDown,我们可以在OnKeyDown中作相应处理。     
        
      BOOL   CSampleControl::PreTranslateMessage(LPMSG   lpmsg)     
      {   
      BOOL   bHandleNow   =   FALSE;   
      switch   (lpmsg->message)   
      {   
      case   WM_KEYDOWN:   
      switch   (lpmsg->wParam)   
      {   
      case   VK_UP:   
      case   VK_DOWN:   
      case   VK_LEFT:   
      case   VK_RIGHT:   
      bHandleNow   =   TRUE;   
      break;   
      }     
      if   (bHandleNow)     
      OnKeyDown(lpmsg->wParam,   LOWORD(lpmsg   ->lParam),   HIWORD(lpmsg->lParam));     
      break;     
      }     
      return   bHandleNow;     
      }     
      

  4.   

    3楼所说///或者直接调用OnKeyDown  多数情况是不可行滴,如果窗口上没有控件还好,当然
    我们首先想到的是响应WM_KEYDOWN消息,但实际运行却发现没有任何效果。   
      原因是对话框里的控件需要首先对按键作出响应,比如多行编辑框必须首先   
      处理回车,不至于回车使对话框关闭。   
      我们要想在第一时间对对话框的按键做出响应,需要重载PreTranslateMessage,  
      

  5.   


    VsirSoft说的没问题啊,你的怎么了?
      

  6.   

    我的dialog是这个样子的
    class CxxxDlg  : public CDialogImpl<CxxxDlg >
      

  7.   

    你的对话框是WTL模板的,仍然是这样处理,你用WTL的向导生成一个Modeless的对话框测试即可. WTL的Modeless对话框是直接调用ShowWindow。WTL本身的示例GuidGen也是一个Modeless对话框的示例
    class CMainDlg : public CDialogImpl<CMainDlg>, public CUpdateUI<CMainDlg>,
    public CMessageFilter, public CIdleHandler
    {
    public:
    enum { IDD = IDD_MAINDLG }; virtual BOOL PreTranslateMessage(MSG* pMsg)
    {
    switch(pMsg->message) 

    case WM_KEYDOWN: 
    switch (pMsg->wParam) 

    case VK_RETURN: 

    ::MessageBox(NULL, L"Return", L"", MB_OK);

    break; 
    case VK_ESCAPE: 
    {
    ::MessageBox(NULL, L"ESC", L"", MB_OK);
    return TRUE;
    }
    }
    break;
    }
    return CWindow::IsDialogMessage(pMsg);
    } virtual BOOL OnIdle()
    {
    return FALSE;
    }
    // .......
    };
      

  8.   

    但是我的PreTranslateMessage call不进来
      

  9.   

    那估计是你直接搞什么破坏了,这是WTL的消息传递机制中的一步,只能你自己先尝试调试。下面是消息的基本过程:int CMessageLoop::Run()
    {
    ......
    if(!PreTranslateMessage(&m_msg))
    {
    ::TranslateMessage(&m_msg);
    ::DispatchMessage(&m_msg);
    }
    ......
    }
    virtual BOOL PreTranslateMessage(MSG* pMsg)
    {
    // loop backwards
    for(int i = m_aMsgFilter.GetSize() - 1; i >= 0; i--)
    {
    CMessageFilter* pMessageFilter = m_aMsgFilter[i];
    if(pMessageFilter != NULL && pMessageFilter->PreTranslateMessage(pMsg))
    return TRUE;
    }
    return FALSE;   // not translated
    }通过CMessageFilter对象,它会把消息传递到PreTranslateMessage方法,因此,你可以尝试在前面的几个地方进行调试,或者看看你的CMessageFilter是否使用错误.
      

  10.   

    很抱歉,前面的回复也许全部都不能用,对应简单的Modeless对话框,可能这样是适合的,但是如果在DoModel的基础至少再显示Modeless对话框,这样估计就不能了,你不能直接取它的CMessageLoop链条。
      

  11.   

    这个时候只能使用HOOK,挂接GetMessage钩子。请参考微软知识库文章:
    http://support.microsoft.com/kb/q187988/ 和
    http://support.microsoft.com/kb/q216503/
      

  12.   

    本帖最后由 laiyiling 于 2008-04-29 12:02:58 编辑
      

  13.   

    消息循环中调用IsDialogMessage,如果返回非0值则继续下次循环。
      

  14.   


    对于这个可能不行,你可以用ATL/WTL试试。若ATL/WTL是通过DoModel建立的消息讯息,微软的建议仍然是HOOK。