TranslateAccelerator成功,但没有显示WM_COMMAND消息

本文关键字:WM COMMAND 消息 显示 成功 TranslateAccelerator | 更新日期: 2023-09-27 18:02:12

我正在编写一个围绕Win32钩子的。net包装器,它缓冲WM_CHAR消息,并允许订阅按键、释放按键和加速按键等事件。一切正常,除了我对TranslateAccelerator的呼叫。当我期望它返回true时(当它在我之前构造的给定表中找到加速器时),但WM_COMMAND消息似乎没有出现过。下面是一些相关的代码。

[StructLayout(LayoutKind.Sequential)]
struct MSG {
    IntPtr hWnd;
    WindowsMessages message;
    IntPtr wParam;
    IntPtr lParam;
    UInt32 time;
    POINT pt;
}
delegate IntPtr HOOKPROC(HookCodes nCode, IntPtr wParam, ref MSG lParam);
[DllImport("user32.dll")] 
extern IntPtr CallNextHookEx(IntPtr hhk, HookCodes nCode, IntPtr wParam, ref MSG lParam);
IntPtr HookProcedure(HookCodes nCode, IntPtr wParam, ref MSG lParam) {
    IntPtr result = IntPtr.Zero;
    if(nCode < HookCodes.ACTION) { 
        result = CallNextHookEx(hHook, nCode, wParam, ref lParam);
    } else if(nCode == HookCodes.ACTION && (PeekMessageOptions)wParam == PeekMessageOptions.REMOVE) {
        /*
         * Under these conditions, each message will only be passed onto the switch below once.
         */
        switch(lParam.message) {
            case WindowsMessages.KEYDOWN: 
                //fire keydown events and call TranslateAccelerator/TranslateMessage
                break;
            case WindowsMessages.KEYUP: 
                //fire keyup events
                break;
            case WindowsMessages.COMMAND: 
                //fire accelerator events Ex: Ctrl+F, ALT+M, SHIFT+L
                break;
            case WindowsMessages.CHAR: 
                //place char in buffer
                break;
            default:
                break;
            }
        }
        return result; //Will be zero if action was taken on the message by this procedure.  
    }
}

在KeyPressed(MSG)中,消息被翻译如下:

[DllImport("user32.dll")]
extern bool TranslateAccelerator(IntPtr hWnd, IntPtr hAccTable, ref MSG lpMsg);
[DllImport("user32.dll")] 
extern bool TranslateMessage(ref MSG lpMsg);
if(!TranslateAccelerator(hWnd, hAccel, ref msg)){
    TranslateMessage(ref msg);
}

钩子和加速表是这样创建的:

[StructLayout(LayoutKind.Sequential)]
struct ACCEL {
    byte fVirt;
    ushort key;
    ushort cmd;
}
[DllImport("user32.dll")] 
extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr lpdwProcessId);
[DllImport("user32.dll")] 
extern IntPtr SetWindowsHookEx(WindowsHooks hook, HookProcedure lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")]
extern IntPtr CreateAcceleratorTable(ACCEL[] lpaccl, int cEntries);
HOOKPROC proc = HookProcedure;
uint pid = GetWindowThreadProcessId(/*IntPtr*/hWnd, IntPtr.Zero);
IntPtr hHook = SetWindowsHookEx(WindowsHooks.GETMESSAGE, proc, IntPtr.Zero, pid);
IntPtr hAccel = CreateAcceleratorTable(/*ACCEL[]*/accelerators, accelerators.Length);

一切都工作得很好(例如将事件附加到按键和缓冲WM_CHAR消息),除了我在队列中的任何地方找不到WM_COMMAND或WM_SYSCOMMAND消息。它们似乎对我的钩子子程不可见,尽管TranslateAccelerator在我期望它返回true时返回true。请注意,当涉及到Win32时,我真的很无能为力,所以我可能错过了一些对训练有素的眼睛来说相当明显的东西。但我已经束手无策了。我试过将钩子连接到XNA窗口和Windows窗体,但没有成功。

TranslateAccelerator成功,但没有显示WM_COMMAND消息

您将无法使用GETMESSAGE钩子捕获这些WM_COMMAND消息。

TranslateAccelerator "将WM_COMMAND或WM_SYSCOMMAND消息直接发送到指定的窗口过程"(见文档),因此绕过消息队列。

你需要一个CALLWNDPROC钩子代替。