我正在编写一个围绕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。请注意,当涉及到Win32时,我真的很无能,所以我可能会错过一些对训练有素的眼睛显而易见的东西。但我在我的智慧结束。我已经尝试将挂钩附加到XNA窗口和Windows窗体但没有成功。
答案 0 :(得分:1)
您不会使用WM_COMMAND
挂钩抓住那些GETMESSAGE
条消息。
TranslateAccelerator
“将WM_COMMAND或WM_SYSCOMMAND消息直接发送到指定的窗口过程”(参见the documentation),从而绕过消息队列。
你需要一个CALLWNDPROC
钩子。