【问题标题】:Windows keyboard accelerators and child windowsWindows 键盘加速器和子窗口
【发布时间】:2009-12-26 05:17:27
【问题描述】:

我已经使用 C 和 Windows API 创建了一个 Windows GUI 程序,并且我希望该程序能够利用键盘加速器。我已经设置了一些可以正常工作的加速器,但是当焦点转到我的程序主窗口的子窗口时,例如列表视图控件或状态栏控件,键盘加速器似乎正在转换为 WM_COMMAND 消息对于子窗口而不是主窗口。因此,当焦点位于子控件上时,我在主窗口的 WndProc 中对相应 WM_COMMAND 消息的处理将被忽略。

我应该如何解决这个问题?

【问题讨论】:

    标签: winapi keyboard wm-command


    【解决方案1】:

    我找到了答案。主窗口的子窗口必须是子类的,这样键盘加速器产生的 WM_COMMAND 消息才能被截获并传递给父窗口。

    这涉及将控件的窗口过程更改为不同的。备用过程通过将它们发送到父窗口来处理应该被截获的消息。指向原始窗口过程的指针也必须存储在某个地方,这样控件才能正常工作。

    可以使用 SetWindowLongPtr 和 GWLP_WNDPROC 更改窗口过程。

    下面是一个简单的例子,说明如何通过将指向原始窗口过程的指针存储在控件的用户数据值 (GWLP_USERDATA) 中:

    更改窗口过程并将原始过程存储在GWLP_USERDATA中的代码:

    SetWindowLongPtr( hWnd, GWLP_USERDATA, ( LONG_PTR )SetWindowLongPtr( hWnd, GWLP_WNDPROC, ( LONG_PTR )WndProc ) );
    

    拦截窗口程序:

    static LRESULT CALLBACK WndProc( const HWND hWnd, const UINT message, const WPARAM wParam, const LPARAM lParam )
    {
        switch( message )
        {
            case WM_COMMAND:
                SendMessage( GetParent( hWnd ), message, wParam, lParam );
                return 0;
            default:
            //Assume that GWLP_USERDATA has been set to the original window procedure.
                return CallWindowProc( ( WNDPROC )GetWindowLongPtr( hWnd, GWLP_USERDATA ), hWnd, message, wParam, lParam );
        }
    }
    

    【讨论】:

      【解决方案2】:

      另一种方法是避免对子窗口使用 TranslateAccelerator,示例代码:

      if (mainWidget() && msg.hwnd == mainWidget()->hwnd()) {
                  if (TranslateAccelerator(msg.hwnd, hMainAccelTable, &msg)) {
                      continue;
                  }
              }
              TranslateMessage(&msg);
              DispatchMessage(&msg);
      

      如果消息不是mainWidget的,我们不使用main widget的加速器表为它翻译加速器。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-16
        • 2010-10-01
        • 2013-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多