TranslateAccelerator завершается успешно, но сообщения WM_COMMAND не отображаются - PullRequest
0 голосов
/ 16 июля 2011

Я пишу оболочку .NET вокруг перехватчиков Win32, которая буферизует сообщения WM_CHAR и позволяет подписываться на такие события, как нажатия клавиш, отпускания клавиш и нажатия клавиш акселератора.Все в рабочем состоянии, кроме, по-видимому, моего звонка TranslateAccelerator.Он возвращает истину, когда я ожидаю этого (когда он находит ускоритель в данной таблице, которую я построил ранее), но сообщения 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, когда я ожидаю этого.Обратите внимание, что я действительно довольно невежественен, когда дело доходит до Win32, поэтому я, вероятно, упускаю что-то довольно очевидное для опытного взгляда.Но я в своем уме.Я безуспешно пытался прикрепить хук к окну XNA и форме Windows.

1 Ответ

1 голос
/ 16 июля 2011

Эти WM_COMMAND сообщения не будут перехвачены GETMESSAGE ловушкой.

TranslateAccelerator "отправляет сообщение WM_COMMAND или WM_SYSCOMMAND непосредственно в указанную оконную процедуру" (см. документацию) и, следовательно, обходит очередь сообщений.

Вместо этого вам потребуется CALLWNDPROC ловушка.

...