【问题标题】:Receiving Ctrl+R message when pressing Ctrl+C in PreTranslateMessage在 PreTranslateMessage 中按 Ctrl+C 时收到 Ctrl+R 消息
【发布时间】:2013-03-15 20:34:06
【问题描述】:

我有一个处理 PreTranslateMessage 中某些消息的 MFC 对话框应用程序。我感兴趣的其中之一是 Ctrl+R。但是,当我单击另一个窗口(Visual Studio 2010 中的代码编辑器、notepad++ 等)并使用 Ctrl+C 复制一些文本(或Ctrl+X)。请注意,使用 Ctrl+V 似乎不会发生这种情况,并且可以使用 GetKeyStateGetASyncKeyState 重现。行为非常混乱!要重现,请在 Visual Studio 10 中创建一个基本的 MFC 对话框,将 pretranslate 添加为:

BOOL CPreTranslateTestDlg::PreTranslateMessage(MSG *pMsg)
{
    if (GetKeyState(VK_CONTROL) & 0x8000 && pMsg->wParam == 'R')
    {
        return true;
    }

    return CDialogEx::PreTranslateMessage(pMsg);
}

return true; 上设置断点,启动对话框。然后转到您的 Visual Studio Code 窗口,然后 Ctrl+C 一些文本;你的断点会被命中。

关于为什么会发生这种情况的任何想法?

【问题讨论】:

    标签: c++ winapi mfc


    【解决方案1】:

    GetKeyState 旨在为您提供键的状态,无论您的对话框是否具有焦点,因此在您的情况下,它正确地指示 Ctrl 已按下。

    其次,您没有检查刚刚发生的消息类型,因此它可能不是 keydown 等。我怀疑正在触发一条与键无关的消息,其 wParam 值恰好等于“R” .

    我会更改代码,以便您检查对话框是否有焦点并使用GetAsyncKeyState 来确定 R 是否也关闭,例如

    BOOL CPreTranslateTestDlg::PreTranslateMessage(MSG *pMsg)
    {
        if (GetKeyState(VK_CONTROL) & 0x8000 && 
         GetKeyState(VK_R) & 0x8000 && 
         GetFocus == this)
        {
            return true;
        }
    
        return CDialogEx::PreTranslateMessage(pMsg);
    }
    

    希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      我这样做是为了在对话框中捕捉键盘快捷键。

      首先,您需要在资源文件中包含要在对话框中使用的加速器的加速器表。

      例如:

      IDR_MYDIALOG_ACCEL

      IDC_CTRL_R    Ctrl+R    Virtkey
      

      在对话框的消息映射中,您应该有这样的内容:

      BEGIN_MESSAGE_MAP(CMyDialogDlg, CDialog)
        //{{AFX_MSG_MAP(CMyDialogDlg)
        ...
          ON_COMMAND(IDC_CTRL_R, OnMyCtrlRHandler)
          ON_WM_DESTROY()
        ...
          //}}AFX_MSG_MAP
      END_MESSAGE_MAP()
      

      OnMyCtrlRHandler 是快捷方式将调用的方法。

      OnInitDialog 中加载加速器表,如下所示:

      BOOL CMyDialogDlg::OnInitDialog()
      {
        ...
          m_hAccel = LoadAccelerators ( AfxGetResourceHandle(), 
                                        MAKEINTRESOURCE(IDR_MYDIALOG_ACCEL) );
        ...
      }
      

      m_hAccelCMyDialogDlg 类型 HACCEL 的成员。

      像这样覆盖 PretranslateMessage:

      BOOL CMyDialogDlg::PreTranslateMessage(MSG* pMsg)
      {
          if (::TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
            return(TRUE);
          else
            return CDialog::PreTranslateMessage(pMsg);
      }
      

      最后你应该在 OnDestroy 处理程序中销毁加速器表:

      void CMyDialogDlg::OnDestroy()
      {
        ...
        DestroyAcceleratorTable(m_hAccel) ;
        ...
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多