c#低电平输入解码消息参数

c#低电平输入解码消息参数,c#,raw-input,low-level,C#,Raw Input,Low Level,我正在制作一个处理全局按键的低级键盘钩子,将其转发到原始输入API以检查它来自哪个键盘设备 我通过使用API可以接收的钩子中的SendMessage函数来实现这一点 我的问题是API无法读取LPRAM的缓冲区,返回false 获取原始输入缓冲区时出错 如何调整钩子以允许API成功解码该消息的LPRAM (我正在使用Rawkeyboard结构,我觉得这可能不是正确的使用方法,我还尝试使用了其他一些结构,但没有成功) 钩住 //^ DLL Imports, SetWindowsHookEx, etc

我正在制作一个处理全局按键的低级键盘钩子,将其转发到原始输入API以检查它来自哪个键盘设备

我通过使用API可以接收的钩子中的
SendMessage
函数来实现这一点

我的问题是API无法读取LPRAM的缓冲区,返回false

获取原始输入缓冲区时出错

如何调整钩子以允许API成功解码该消息的LPRAM

(我正在使用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);
    }
}

HookProc
SendMessage(WM\u输入)
lParam
类型不同

对于
HookProc
,它的结构是

对于
发送消息(WM\U输入)
,它的结构是


因此,您需要创建一个新的
RAWINPUT
对象,然后传递给
SendMessage
方法。
HookProc
SendMessage(WM_输入)
lParam
类型不同

对于
HookProc
,它的结构是

对于
发送消息(WM\U输入)
,它的结构是


因此,您需要创建一个新的
RAWINPUT
对象,然后传递给
SendMessage
方法。

您可以尝试使用
if(Win32.GetRawInputData(…)!=dwSize
,并确认是否仍然出现错误?@Xiaoy312是的,仍然是相同的错误,但切换运算符无效,谢谢!)捕获第一个api的结果并检查最后一个错误<代码>变量结果=Win32.GetRaw…();如果(result=-1){var code=Marshal.GetLastWin32Error();var error=new Win32Exception(code);Debug.WriteLine(code+“:“+error.ToString());}检查这是否给了您任何帮助。哇,谢谢!我得到一个
System.ComponentModel.Win32Exception(0x80004005):句柄无效
错误,这一定与@shingo的响应有关,你可以尝试
if(Win32.GetRawInputData(…)!=dwSize
,确认你是否仍然得到错误?@Xiaoy312是的,仍然是相同的错误,但是切换操作符无效,谢谢!)捕获第一个api的结果并检查最后一个错误<代码>变量结果=Win32.GetRaw…();如果(result=-1){var code=Marshal.GetLastWin32Error();var error=new Win32Exception(code);Debug.WriteLine(code+“:“+error.ToString());}检查这是否给了您任何帮助。哇,谢谢!我得到一个
System.ComponentModel.Win32Exception(0x80004005):句柄无效
错误,这一定与@shingo的responceHey有关,你能看看我的编辑,看看它们是否是你建议的,仍然得到相同的错误;(我错了,发送WM_输入消息需要RAWINPUT结构,它包含RAWKEYBOARD结构。嘿,你能看看我的编辑是否是你建议的,仍然得到相同的错误;(我错了,发送WM_输入消息需要RAWINPUT结构,它包含RAWKEYBOARD结构。)。