开发者

TranslateAccelerator succeeds, but WM_COMMAND messages are not showing up

开发者 https://www.devze.com 2023-03-21 05:46 出处:网络
I am writing a .NET wrapper around Win32 hooks which buffers WM_CHAR messages and allows events such as key presses, key releases, and accelerator keystrokes to be subscribed to. Everything is in work

I am writing a .NET wrapper around Win32 hooks which buffers WM_CHAR messages and allows events such as key presses, key releases, and accelerator keystrokes to be subscribed to. Everything is in working order except apparently my call to TranslateAcce开发者_StackOverflow中文版lerator. It returns true when I expect it to (when it finds an accelerator in the given table which I constructed earlier) but the WM_COMMAND messages don't seem to be showing up ever. Here is some relevant code.

[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.  
    }
}

In KeyPressed(MSG), messages are translated like so:

[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);
}

The hook and accelerator table are created like this:

[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);

Everything works fine (such as attaching events to key-downs and buffering WM_CHAR messages) except I can't find WM_COMMAND or WM_SYSCOMMAND messages anywhere in the queue. They just don't seem to be visible to my hook procedure, even though TranslateAccelerator returns true when I expect it to. Note that I am really pretty clueless when it comes to Win32 so I'm probably missing something fairly obvious to the trained eye. But I am at my wits end. I've tried attaching the hook to an XNA window and a Windows Form without success.


You won't catch those WM_COMMAND messages with a GETMESSAGE hook.

TranslateAccelerator "sends the WM_COMMAND or WM_SYSCOMMAND message directly to the specified window procedure" (see the documentation) and hence bypasses the message queue.

You'll need a CALLWNDPROC hook instead.

0

精彩评论

暂无评论...
验证码 换一张
取 消