SY.*_*SY. 0 keyboard winapi dialog
我有一个带有主窗口的应用程序,它有一堆控件,包括空格键,它由一个叫做的简单方法处理onSpacebar().在那个主窗口的顶部,我有一个持久的无模式对话框.无论对话框是否具有焦点,或者主窗口具有焦点,我都需要空格键的行为方式完全相同.
这个对话框由DialogProc支持,它看起来像这样:
BOOL CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_NOTIFY:
std::cout<< "WM_NOTIFY" <<std::endl;
switch(LOWORD(wParam))
{
// which component caused the message?
case COMP_TREE:
if(((LPNMHDR)lParam)->code == NM_DBLCLK){
onDoubleclk()
}
//...
break;
// other components...
}
break;
case WM_CLOSE:
// the dialog can only be closed when the whole app is closed
//EndDialog(hDlg, IDCANCEL);
return TRUE;
case WM_DESTROY:
PostQuitMessage(0);
return TRUE;
}
return FALSE;
}
Run Code Online (Sandbox Code Playgroud)
从我收集的内容中,我应该onSpacebar()在DialogProc中调用我的方法,类似于我如何处理双击.我可以看到,WM_NOTIFY当按下空格键时,对话框会收到该对话框(短语WM_NOTIFY被打印到cout),但我似乎无法将空格键通知与对话框收到的其他众多通知区分开来.
请告诉我如何识别特定WM_NOTIFY是响应空格键按键.
一个WM_NOTIFY消息是不是一个窗口处理按键事件的标准方式.当按下一个键,您的窗口应该接收WM_KEYDOWN,WM_KEYUP以及可能的WM_CHAR消息.WM_NOTIFY完全不同的目的:将消息从公共控件传递到其父窗口.
因此WM_NOTIFY,当您理解焦点如何工作时(这是解决您的最终问题的关键),您在接收按键时收到消息的事实是相当不寻常的事情.
在Windows中,一次只能聚焦一个窗口,当前聚焦的窗口是接收所有键盘输入的窗口.因此,如果对话框具有焦点,它将接收按键通知.如果该对话框上的子控件具有焦点,则它(不是其父对话框)将接收按键通知.并且在对话框上有一个可聚焦的子控件,它总是会优先于其父对话框获得焦点,因此它也总是会收到按键通知.
因此,对您的好奇WM_NOTIFY消息的可能解释是,对话框中的一个常用控件具有焦点,它正在接收空格键按下事件,并且在处理它之后,将通知传递到其父窗口(您的对话框)中.WM_NOTIFY消息的形式.正如您可能想象的那样,这不是检测空格键被按下的可靠方法.
相反,您需要找出一些方法来捕获按键通知,然后才能将它们发送到聚焦控件.为此,您需要在调用或之前修改应用程序的消息循环以捕获WM_KEYDOWN或WM_KEYUP消息.DispatchMessageIsDialogMessage
onSpacebar函数并指示该消息已被处理,从而阻止它被另一个窗口传递和处理.由于这种方法在全局范围内过滤掉空格键按下,因此它解决了在窃取按键的对话框和其他无模式对话框中的子控件问题.但是,您需要小心,因为它很容易搞砸,因此用户根本无法使用键盘导航对话框.
更根本的是,我认为你处理空格键压力的想法存在根本缺陷.某些常用控件的逻辑基本上要求他们处理空格键的按压.例如,考虑一个文本框:如果您在全局级别过滤掉空格键的所有按下,则用户将永远无法在文本框中键入空格.如果您坚持处理空格键,则需要检查全局处理程序中的焦点控件,如果它是文本框(或您希望接收空格的其他常用控件),则将其传递给; 否则,自己处理.
老实说,我要做的是选择一个更独特的组合键(比如,我不知道,Ctrl+ Space)并将其设置为加速器.据推测,您的全局消息循环已经通过调用该TranslateAccelerator函数来处理加速键,因此将为您处理所有脏工作.甚至不需要代码 - 只需编辑项目中的加速器资源文件即可完成所有操作.关于键盘加速器的MSDN文档就在这里,但您可能更容易在Visual C++上查阅自己喜爱的书籍.
| 归档时间: |
|
| 查看次数: |
1718 次 |
| 最近记录: |