Windows键盘加速器和子窗口

时间:2009-12-26 05:17:27

标签: winapi keyboard wm-command

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

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

我找到了答案。主窗口的子窗口必须是子类,以便键盘加速器生成的WM_COMMAND消息可以被拦截并传递给父窗口。

这涉及将控件的窗口过程更改为其他窗口过程。备用过程通过将它们发送到父窗口来处理应该被截获的消息。还必须将指向原始窗口过程的指针存储在某处,以便控件可以正常运行。

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

下面是一个简单的示例,说明如何通过在控件的用户数据值(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 );
    }
}

答案 1 :(得分:0)

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

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

如果消息不是mainWidget,我们不会使用主窗口小部件的加速器表来为它加速。