Winapi Windows键盘加速器和子窗口

Winapi Windows键盘加速器和子窗口,winapi,keyboard,wm-command,Winapi,Keyboard,Wm Command,我已经使用C和Windows API创建了一个Windows GUI程序,我希望该程序使用键盘加速器。我已经设置了一些加速器,它们工作正常,但当焦点转到程序主窗口的子窗口(如列表视图控件或状态栏控件)时,键盘加速器似乎被转换为子窗口而不是主窗口的WM_命令消息。因此,当焦点在子控件上时,我在主窗口的WndProc中对适当的WM_命令消息的处理被忽略 我该如何解决这个问题?我找到了答案。主窗口的子窗口必须子类化,以便可以截获键盘加速器生成的WM_命令消息并将其传递给父窗口 这涉及将控件的窗口过程更

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


我该如何解决这个问题?

我找到了答案。主窗口的子窗口必须子类化,以便可以截获键盘加速器生成的WM_命令消息并将其传递给父窗口

这涉及将控件的窗口过程更改为其他过程。备用过程通过将消息发送到父窗口来处理应该截获的消息。指向原始窗口过程的指针也必须存储在某个位置,以便控件能够正常工作

可以使用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 );
    }
}

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

if (mainWidget() && msg.hwnd == mainWidget()->hwnd()) {
            if (TranslateAccelerator(msg.hwnd, hMainAccelTable, &msg)) {
                continue;
            }
        }
        TranslateMessage(&msg);
        DispatchMessage(&msg);
如果消息不是mainWidget的,我们不会使用mainWidget的加速器表为其翻译加速器