我正在制作一个用于处理全局按键的低级键盘挂钩,并将其转发到Raw Input API,以检查其来自哪个键盘设备。
我通过在钩子中使用SendMessage
函数来实现此目的,该函数可以被API接收。
我的问题是API无法读取lParam的缓冲区,返回false
>> Error getting the rawinput buffer
如何调整该钩子,以使该消息的lParam被API成功解码?
(我正在使用Rawkeyboard结构,但我觉得这可能不是正确的方法,我也尝试过使用其他一些运气不好的方法)
挂钩
//^ DLL Imports, SetWindowsHookEx, etc^
public int HookProc(int Code, int wParam, ref CWPRETSTRUCT lParam) {
if (Code >= 0) {
// Block
Rawkeyboard lParamKeyboard = new Rawkeyboard();
int result = SendMessage(Handle, 0x00FF, wParam, ref lParamKeyboard ); // Send to API
if (result == 1) {
return 1;
}
}
// Allow
return CallNextHookEx(Handle, Code, wParam, ref lParam);
}
[StructLayout(LayoutKind.Sequential)]
public struct Rawkeyboard {
public ushort Makecode; // Scan code from the key depression
public ushort Flags; // One or more of RI_KEY_MAKE, RI_KEY_BREAK, RI_KEY_E0, RI_KEY_E1
private readonly ushort Reserved; // Always 0
public ushort VKey; // Virtual Key Code
public uint Message; // Corresponding Windows message for exmaple (WM_KEYDOWN, WM_SYASKEYDOWN etc)
public uint ExtraInformation; // The device-specific addition information for the event (seems to always be zero for keyboards)
public override string ToString() {
return string.Format("Rawkeyboard\n Makecode: {0}\n Makecode(hex) : {0:X}\n Flags: {1}\n Reserved: {2}\n VKeyName: {3}\n Message: {4}\n ExtraInformation {5}\n",
Makecode, Flags, Reserved, VKey, Message, ExtraInformation);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct CWPRETSTRUCT {
IntPtr lResult;
IntPtr lParam;
IntPtr wParam;
uint message;
IntPtr hWnd;
}
API
protected override void WndProc(ref Message message){
switch (message.Msg){
// Message Received!
case 0x00FF:{
bool result = false;
hdevice = message.LParam;
if (_deviceList.Count == 0) return false;
var dwSize = 0;
Win32.GetRawInputData(hdevice, DataCommand.RID_INPUT, IntPtr.Zero, ref dwSize, Marshal.SizeOf(typeof(Rawinputheader)));
if (dwSize != Win32.GetRawInputData(hdevice, DataCommand.RID_INPUT, out _rawBuffer, ref dwSize, Marshal.SizeOf(typeof (Rawinputheader)))){
Debug.WriteLine("Error getting the rawinput buffer");
result = false;
}
else{
// Do checks here
result = true;
}
message.Result = (IntPtr)Convert.ToInt32(result);
}
break;
}
base.WndProc(ref message);
}
[StructLayout(LayoutKind.Sequential)]
public struct Rawinputheader
{
public uint dwType; // Type of raw input (RIM_TYPEHID 2, RIM_TYPEKEYBOARD 1, RIM_TYPEMOUSE 0)
public uint dwSize; // Size in bytes of the entire input packet of data. This includes RAWINPUT plus possible extra input reports in the RAWHID variable length array.
public IntPtr hDevice; // A handle to the device generating the raw input data.
public IntPtr wParam; // RIM_INPUT 0 if input occurred while application was in the foreground else RIM_INPUTSINK 1 if it was not.
public override string ToString()
{
return string.Format("RawInputHeader\n dwType : {0}\n dwSize : {1}\n hDevice : {2}\n wParam : {3}", dwType, dwSize, hDevice, wParam);
}
}
答案 0 :(得分:2)
lParam
和HookProc
的{{1}}的类型不同。
对于SendMessage(WM_INPUT)
,它是CWPRETSTRUCT结构。
对于HookProc
,它是RAWINPUT结构。
因此,您需要创建一个新的SendMessage(WM_INPUT)
对象,然后传递给RAWINPUT
方法。