无模式对话框键盘处理(winapi)

无模式对话框键盘处理(winapi),winapi,dialog,keyboard,Winapi,Dialog,Keyboard,我有一个应用程序,它有一个主窗口,其中有一系列控件,包括空格键,它由一个名为onSpacebar()的简单方法处理。在主窗口的顶部,我有一个持久的无模式对话框。 我需要空格键以完全相同的方式运行,无论对话框是否具有焦点,或主窗口是否具有焦点 此对话框由DialogProc支持,其外观如下: BOOL CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg)

我有一个应用程序,它有一个主窗口,其中有一系列控件,包括空格键,它由一个名为
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;
    }
BOOL回调对话框proc(HWND hDlg、UINT uMsg、WPARAM WPARAM、LPARAM LPARAM)
{
开关(uMsg)
{
案件通知:
std::cout消息不是窗口处理按键事件的标准方式。当按下一个键时,您的窗口应该会收到消息,可能还会收到消息。
WM\u NOTIFY
的用途完全不同:将消息从一个公共控件传递到其父窗口

因此,当您了解焦点是如何工作的(这是解决最终问题的关键)时,您会收到一条响应按键的
WM\u NOTIFY
消息,这是一件相当不寻常的事情

在Windows中,一次只能聚焦一个窗口,而当前聚焦的窗口是接收所有键盘输入的窗口。因此,如果对话框具有焦点,则它将接收按键通知。如果该对话框上的子控件具有焦点,则它(而非其父对话框)将接收按键通知。对话框上有一个可聚焦的子控件,它将始终优先于其父对话框接收焦点,因此它也将始终接收按键通知

因此,对于您好奇的
WM_NOTIFY
消息,可能的解释是,对话框上的一个具有焦点,它接收空格键按下事件,并在处理它之后,将通知传递给其父窗口(您的对话框)以
WM_NOTIFY
消息的形式。正如您所想象的,这不是检测空格键已按下的可靠方法

相反,在按键通知发送到焦点控件之前,您需要找出某种捕获方式。为此,您需要在调用或之前修改应用程序的消息循环,以捕获
WM\u KEYDOWN
WM\u keydup
消息

  • 如果按键事件对应于空格键,您将调用
    onSpacebar
    函数并指示消息已被处理,从而防止消息被其他窗口传递和处理
  • 如果键事件与空格键不对应,则需要像通常那样处理消息,确保消息确实被另一个窗口传递和处理
由于这种方法在全局级别过滤掉空格键,它解决了对话框上的子控件窃取按键和其他无模式对话框的问题。但是,您确实需要小心,因为它很容易出错,用户根本无法使用键盘浏览您的对话框

<> P>更基本的是,我认为<强>你处理空间条的按压的想法从根本上是有缺陷的< /强>。某些公共控件的逻辑基本上要求它们处理空格键的压力机。例如,考虑一个文本框:如果在全局级别中过滤出空格键的所有按压,用户将永远不能。在文本框中键入空格。如果您坚持要处理空格栏,则需要检查全局处理程序中的焦点控件,如果它是文本框(或您希望接收空格的其他常用控件),请将其传递给其他人;否则,请自行处理

老实说,我要做的是选择一个更独特的组合键(比如,我不知道,Ctrl+Space)并将其设置为加速器。大概,您的全局消息循环已经通过调用该函数来处理加速器键,这样就可以为您处理所有脏活。甚至不需要代码,您只需编辑项目中的加速器资源文件即可完成所有工作。keyboard accelera上的MSDN文档Tor是,但是你可能会更容易地在Visual C++上查阅你喜欢的书。

< P>消息不是窗口处理按键事件的标准方式。当按下一个键时,你的窗口应该接收,可能是消息。<代码> WMXNOTECT/<代码>完全不同的用途:传递一个消息。从一个公共控件转到其父窗口

因此,当您了解焦点是如何工作的(这是解决最终问题的关键)时,您会收到一条响应按键的
WM\u NOTIFY
消息,这是一件相当不寻常的事情

在Windows中,一次只能聚焦一个窗口,而当前聚焦的窗口是接收所有键盘输入的窗口。因此,如果对话框具有焦点,则它将接收按键通知。如果该对话框上的子控件具有焦点,则它(而非其父对话框)将接收按键通知。对话框上有一个可聚焦的子控件,它将始终优先于其父对话框接收焦点,因此它也将始终接收按键通知

因此,对于您好奇的
WM_NOTIFY
消息,可能的解释是,对话框上的一个具有焦点,它接收空格键按下事件,并在处理它之后,将通知传递给其父窗口(您的对话框)以
WM_NOTIFY
消息的形式。正如您所想象的,这不是检测空格键已按下的可靠方法

相反,在按键通知被发送到焦点控件之前,您需要找出某种捕获方式。为此,您需要将应用程序的消息循环修改为trap
WM_KE