我有一个MFC对话框应用程序,用于处理PreTranslateMessage中的某些消息。我感兴趣的其中一个是Ctrl + R.但是,当我单击另一个窗口(visual studio 2010中的代码编辑器,nodepad ++等)并使用Ctrl + C(或Ctrl + X)复制一些文本时,我收到此消息。请注意,使用Ctrl + V似乎不会发生这种情况,并且可以使用GetKeyState和GetASyncKeyState重现。这种行为非常混乱!若要重现,请在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代码窗口,然后按Ctrl + C一些文本;你的断点将被击中。
关于为什么会发生这种情况的任何想法?
答案 0 :(得分:5)
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);
}
希望这有帮助。
答案 1 :(得分:0)
我这样做是为了捕捉对话框中的键盘快捷键。
首先,您需要在资源文件中包含一个加速器表,其中包含您要在对话框中使用的加速器。
例如:
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_hAccel是HACCEL类型的CMyDialogDlg的成员。
像这样覆盖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) ;
...
}