WH_MOUSE_LL钩子不会被调用注入事件(mouse_event,SendInput)

我的代码使用WH_MOUSE_LL钩子来最初禁止所有的鼠标input,除非dwExtraInfo属性被设置为一个特定的值。 该程序还注册了鼠标设备的原始input,以便我可以识别哪个设备负责input。 当我得到一个WM_INPUT消息,并确定源,取决于设备,我可能只是想让事件生效,在这种情况下,我用SendInput(尝试mouse_event,已被取代,以及)重新创build它,提供数据在dwExtraInfo属性中。 这个想法是,钩子应该看到这个新的注入事件,看到额外的信息,而不是压制它。 不幸的是,注入的事件从来没有被钩住。 相应的WM_INPUT消息被窗口过程看到,而SendInput返回1,所以似乎事件正在被生成。 我已经读了上下文切换到安装钩子的线程,并且它必须有一个消息循环。 我相信我的代码满足该限定(因为Application.Run()在线程上启动一个消息循环 – 我也尝试了一个手写的Win32风格的消息循环)。 任何人有任何想法,为什么这是发生和/或如何解决这个问题?

下面的代码展示了这个问题。 它应该引用System和System.Windows.Forms。

主要课程:

using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Windows.Forms; using Win32; public class LLMH : Form { private static LowLevelMouseProc _proc = HookCallback; private static IntPtr _hookID = IntPtr.Zero; private InputProcessor inputProcessor; private static IntPtr extraInfoPointer; private const int EXTRA_INFO = 1000; public static void Main() { _hookID = SetHook(_proc); LLMH app = new LLMH(); app.inputProcessor = new InputProcessor(); app.RegisterDevice(0x01, 0x02, (int)RawInputDeviceFlag.RIDEV_INPUTSINK); int extraInfo = EXTRA_INFO; LLMH.extraInfoPointer = new IntPtr(extraInfo); Application.Run(); UnhookWindowsHookEx(_hookID); } public void RegisterDevice(ushort usagePage, ushort usage, int flags) { inputProcessor.RegisterDevice(usagePage, usage, flags, this.Handle); } protected override void WndProc(ref Message message) { switch (message.Msg) { case (int)WindowsMessage.WM_INPUT: Console.WriteLine("Received WM_INPUT."); RawInput rawInput = inputProcessor.GetRawInput(ref message); String name = inputProcessor.GetRawInputDeviceName(rawInput); Console.WriteLine("rawInput.extraInfo: {0}", rawInput.mouse.extraInformation); if (rawInput.mouse.extraInformation != EXTRA_INFO) { Console.WriteLine("Creating local mouse event."); //mouse_event( // (int)rawInput.mouse.flags, // rawInput.mouse.lastX, // rawInput.mouse.lastY, // rawInput.mouse.buttonData, // extraInfoPointer); INPUT input = new INPUT(); input.type = (int)RawInputType.MOUSE; input.mkhi.mi.dwFlags = (uint)rawInput.mouse.flags; input.mkhi.mi.dx = rawInput.mouse.lastX; input.mkhi.mi.dy = rawInput.mouse.lastY; input.mkhi.mi.mouseData = rawInput.mouse.buttonData; input.mkhi.mi.dwExtraInfo = extraInfoPointer; Console.WriteLine("Return value of SendInput: {0}", SendInput(1, ref input, Marshal.SizeOf(input))); } base.WndProc(ref message); break; default: base.WndProc(ref message); break; } } private static IntPtr SetHook(LowLevelMouseProc proc) { using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { return SetWindowsHookEx((int)WindowsHook.WH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0); } } private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam); private static IntPtr HookCallback( int nCode, IntPtr wParam, IntPtr lParam) { Console.WriteLine("\nIn hook."); if (nCode >= 0) { MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)); if (hookStruct.dwExtraInfo == LLMH.extraInfoPointer) { Console.WriteLine("Extra info matches. hookStruct.dwExtraInfo: {0}", hookStruct.dwExtraInfo); } else { Console.WriteLine("Extra info doesn't match. hookStruct.dwExtraInfo: {0}", hookStruct.dwExtraInfo); return new IntPtr(-1); } } return CallNextHookEx(_hookID, nCode, wParam, lParam); } [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr GetModuleHandle(string lpModuleName); [DllImport("user32.dll", SetLastError = true)] public static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize); [DllImport("user32.dll")] public static extern void mouse_event(Int32 dwFlags, Int32 dx, Int32 dy, Int32 dwData, IntPtr dwExtraInfo); } 

InputProcessor类:

 using System; using System.Runtime.InteropServices; using System.Windows.Forms; using Win32; public class InputProcessor { public RawInput GetRawInput(ref Message message) { uint size = 0; // Call with null pointer to get amount of memory required for buffer. GetRawInputData( message.LParam, (uint)RawInputDeviceCommand.RID_INPUT, IntPtr.Zero, ref size, (uint)Marshal.SizeOf(typeof(RawInputHeader))); IntPtr buffer = Marshal.AllocHGlobal((int)size); if (GetRawInputData( message.LParam, (uint)RawInputDeviceCommand.RID_INPUT, buffer, ref size, (uint)Marshal.SizeOf(typeof(RawInputHeader))) == size) { RawInput input = (RawInput)Marshal.PtrToStructure(buffer, typeof(RawInput)); Marshal.FreeHGlobal(buffer); return input; } else { throw new ApplicationException("Failed to return Raw Input"); } } public String GetRawInputDeviceName(RawInput rawInput) { uint length = 0; // Determine amount of memory to allocate for device name. GetRawInputDeviceInfo( rawInput.header.device, (uint)RawInputDeviceCommand.RIDI_DEVICENAME, IntPtr.Zero, ref length); String deviceName = String.Empty; if (length > 0) { IntPtr data = Marshal.AllocHGlobal((int)length); GetRawInputDeviceInfo(rawInput.header.device, (uint)RawInputDeviceCommand.RIDI_DEVICENAME, data, ref length); deviceName = (String)Marshal.PtrToStringAnsi(data); Marshal.FreeHGlobal(data); } return deviceName; } public void RegisterDevice(ushort usagePage, ushort usage, int flags, IntPtr windowHandle) { RawInputDevice[] inputDevices = new RawInputDevice[1]; inputDevices[0].usagePage = usagePage; inputDevices[0].usage = usage; inputDevices[0].flags = flags; inputDevices[0].windowHandle = windowHandle; if (!RegisterRawInputDevices(inputDevices, (uint)inputDevices.Length, (uint)Marshal.SizeOf(inputDevices[0]))) { throw new ApplicationException("Failed to register raw input devices."); } } [DllImport("user32.dll", SetLastError = true)] public static extern uint GetRawInputDeviceInfo( IntPtr deviceHandle, uint command, IntPtr data, ref uint size); [DllImport("User32.dll")] public static extern bool RegisterRawInputDevices( RawInputDevice[] rawInputDevice, uint numDevices, uint size); [DllImport("User32.dll")] public static extern int GetRawInputData( IntPtr rawInput, uint command, IntPtr data, ref uint size, uint headerSize); [DllImport("user32.dll")] public static extern uint GetRawInputDeviceList( IntPtr rawInputDeviceList, ref uint numDevices, uint size); } 

额外的P / Invoke结构,枚举等

 using System; using System.Runtime.InteropServices; namespace Win32 { public enum WindowsMessage { WM_NULL = 0x0000, WM_CREATE = 0x0001, WM_DESTROY = 0x0002, WM_MOVE = 0x0003, WM_SIZE = 0x0005, WM_ACTIVATE = 0x0006, WM_SETFOCUS = 0x0007, WM_KILLFOCUS = 0x0008, WM_QUIT = 0x0012, WM_INPUT = 0x00FF, WM_LBUTTONDOWN = 0x0201, WM_LBUTTONUP = 0x0202, WM_MOUSEMOVE = 0x0200, WM_MOUSEWHEEL = 0x020A, WM_RBUTTONDOWN = 0x0204, WM_RBUTTONUP = 0x0205 } public enum WindowsHook { WH_MOUSE_LL = 14 } [StructLayout(LayoutKind.Sequential)] public struct POINT { public int x; public int y; } [StructLayout(LayoutKind.Sequential)] public struct MSLLHOOKSTRUCT { public POINT pt; public uint mouseData; public uint flags; public uint time; public IntPtr dwExtraInfo; } // Raw Input section. [StructLayout(LayoutKind.Sequential)] public struct RawInput { public RawInputHeader header; public RawInputMouse mouse; public RawInputKeyboard keyboard; public RawInputHID hid; } [StructLayout(LayoutKind.Sequential)] public struct RawInputHeader { public RawInputType type; public int size; public IntPtr device; public IntPtr wParam; } [StructLayout(LayoutKind.Sequential)] public struct RawInputMouse { public RawMouseFlags flags; public ushort buttonData; public RawMouseButtons buttonflags; public uint rawButtons; public int lastX; public int lastY; public uint extraInformation; } [StructLayout(LayoutKind.Sequential)] public struct RawInputKeyboard { public ushort makeCode; public ushort flags; public ushort reserved; public ushort virtualKeyCode; public uint message; public ulong extraInformation; } [StructLayout(LayoutKind.Sequential)] public struct RawInputHID { public int size; public int count; public IntPtr data; } public enum RawInputType { MOUSE = 0, KEYBOARD = 1, HID = 2 } [Flags()] public enum RawMouseFlags : ushort { MOVE_RELATIVE = 0, MOVE_ABSOLUTE = 1, VIRTUAL_DESKTOP = 2, ATTRIBUTES_CHANGED = 4 } [Flags()] public enum RawMouseButtons : ushort { None = 0, LeftDown = 0x0001, LeftUp = 0x0002, RightDown = 0x0004, RightUp = 0x0008, MiddleDown = 0x0010, MiddleUp = 0x0020, Button4Down = 0x0040, Button4Up = 0x0080, Button5Down = 0x0100, Button5Up = 0x0200, MouseWheel = 0x0400 } [StructLayout(LayoutKind.Sequential)] public struct RawInputDeviceList { public IntPtr device; public uint type; } [StructLayout(LayoutKind.Sequential)] public struct RawInputDevice { [MarshalAs(UnmanagedType.U2)] public ushort usagePage; [MarshalAs(UnmanagedType.U2)] public ushort usage; [MarshalAs(UnmanagedType.U4)] public int flags; public IntPtr windowHandle; } public enum RawInputDeviceFlag : int { RIDEV_REMOVE = 0x00000001, RIDEV_EXCLUDE = 0x00000010, RIDEV_PAGEONLY = 0x00000020, RIDEV_NOLEGACY = 0x00000030, RIDEV_INPUTSINK = 0x00000100, RIDEV_CAPTUREMOUSE = 0x00000200, RIDEV_NOHOTKEYS = 0x00000200, RIDEV_APPKEYS = 0x00000400, RIDEV_EXMODEMASK = 0x00000F0 } public enum RawInputDeviceCommand : int { RID_INPUT = 0x10000003, RIDI_DEVICENAME = 0x20000007, RIDI_DEVICEINFO = 0x2000000b } public enum HIDUsage : ushort { Pointer = 0x01, Mouse = 0x02, Joystick = 0x04, Gamepad = 0x05, Keyboard = 0x06, Keypad = 0x07, SystemControl = 0x80, X = 0x30, Y = 0x31, Z = 0x32, RelativeX = 0x33, RelativeY = 0x34, RelativeZ = 0x35, Slider = 0x36, Dial = 0x37, Wheel = 0x38, HatSwitch = 0x39, CountedBuffer = 0x3A, ByteCount = 0x3B, MotionWakeup = 0x3C, VX = 0x40, VY = 0x41, VZ = 0x42, VBRX = 0x43, VBRY = 0x44, VBRZ = 0x45, VNO = 0x46, SystemControlPower = 0x81, SystemControlSleep = 0x82, SystemControlWake = 0x83, SystemControlContextMenu = 0x84, SystemControlMainMenu = 0x85, SystemControlApplicationMenu = 0x86, SystemControlHelpMenu = 0x87, SystemControlMenuExit = 0x88, SystemControlMenuSelect = 0x89, SystemControlMenuRight = 0x8A, SystemControlMenuLeft = 0x8B, SystemControlMenuUp = 0x8C, SystemControlMenuDown = 0x8D, KeyboardNoEvent = 0x00, KeyboardRollover = 0x01, KeyboardPostFail = 0x02, KeyboardUndefined = 0x03, KeyboardaA = 0x04, KeyboardzZ = 0x1D, Keyboard1 = 0x1E, Keyboard0 = 0x27, KeyboardLeftControl = 0xE0, KeyboardLeftShift = 0xE1, KeyboardLeftALT = 0xE2, KeyboardLeftGUI = 0xE3, KeyboardRightControl = 0xE4, KeyboardRightShift = 0xE5, KeyboardRightALT = 0xE6, KeyboardRightGUI = 0xE7, KeyboardScrollLock = 0x47, KeyboardNumLock = 0x53, KeyboardCapsLock = 0x39, KeyboardF1 = 0x3A, KeyboardF12 = 0x45, KeyboardReturn = 0x28, KeyboardEscape = 0x29, KeyboardDelete = 0x2A, KeyboardPrintScreen = 0x46, LEDNumLock = 0x01, LEDCapsLock = 0x02, LEDScrollLock = 0x03, LEDCompose = 0x04, LEDKana = 0x05, LEDPower = 0x06, LEDShift = 0x07, LEDDoNotDisturb = 0x08, LEDMute = 0x09, LEDToneEnable = 0x0A, LEDHighCutFilter = 0x0B, LEDLowCutFilter = 0x0C, LEDEqualizerEnable = 0x0D, LEDSoundFieldOn = 0x0E, LEDSurroundFieldOn = 0x0F, LEDRepeat = 0x10, LEDStereo = 0x11, LEDSamplingRateDirect = 0x12, LEDSpinning = 0x13, LEDCAV = 0x14, LEDCLV = 0x15, LEDRecordingFormatDet = 0x16, LEDOffHook = 0x17, LEDRing = 0x18, LEDMessageWaiting = 0x19, LEDDataMode = 0x1A, LEDBatteryOperation = 0x1B, LEDBatteryOK = 0x1C, LEDBatteryLow = 0x1D, LEDSpeaker = 0x1E, LEDHeadset = 0x1F, LEDHold = 0x20, LEDMicrophone = 0x21, LEDCoverage = 0x22, LEDNightMode = 0x23, LEDSendCalls = 0x24, LEDCallPickup = 0x25, LEDConference = 0x26, LEDStandBy = 0x27, LEDCameraOn = 0x28, LEDCameraOff = 0x29, LEDOnLine = 0x2A, LEDOffLine = 0x2B, LEDBusy = 0x2C, LEDReady = 0x2D, LEDPaperOut = 0x2E, LEDPaperJam = 0x2F, LEDRemote = 0x30, LEDForward = 0x31, LEDReverse = 0x32, LEDStop = 0x33, LEDRewind = 0x34, LEDFastForward = 0x35, LEDPlay = 0x36, LEDPause = 0x37, LEDRecord = 0x38, LEDError = 0x39, LEDSelectedIndicator = 0x3A, LEDInUseIndicator = 0x3B, LEDMultiModeIndicator = 0x3C, LEDIndicatorOn = 0x3D, LEDIndicatorFlash = 0x3E, LEDIndicatorSlowBlink = 0x3F, LEDIndicatorFastBlink = 0x40, LEDIndicatorOff = 0x41, LEDFlashOnTime = 0x42, LEDSlowBlinkOnTime = 0x43, LEDSlowBlinkOffTime = 0x44, LEDFastBlinkOnTime = 0x45, LEDFastBlinkOffTime = 0x46, LEDIndicatorColor = 0x47, LEDRed = 0x48, LEDGreen = 0x49, LEDAmber = 0x4A, LEDGenericIndicator = 0x3B, TelephonyPhone = 0x01, TelephonyAnsweringMachine = 0x02, TelephonyMessageControls = 0x03, TelephonyHandset = 0x04, TelephonyHeadset = 0x05, TelephonyKeypad = 0x06, TelephonyProgrammableButton = 0x07, SimulationRudder = 0xBA, SimulationThrottle = 0xBB } public enum HIDUsagePage : ushort { Undefined = 0x00, Generic = 0x01, Simulation = 0x02, VR = 0x03, Sport = 0x04, Game = 0x05, Keyboard = 0x07, LED = 0x08, Button = 0x09, Ordinal = 0x0A, Telephony = 0x0B, Consumer = 0x0C, Digitizer = 0x0D, PID = 0x0F, Unicode = 0x10, AlphaNumeric = 0x14, Medical = 0x40, MonitorPage0 = 0x80, MonitorPage1 = 0x81, MonitorPage2 = 0x82, MonitorPage3 = 0x83, PowerPage0 = 0x84, PowerPage1 = 0x85, PowerPage2 = 0x86, PowerPage3 = 0x87, BarCode = 0x8C, Scale = 0x8D, MSR = 0x8E } // SendInput section. [StructLayout(LayoutKind.Sequential)] public struct MOUSEINPUT { public int dx; public int dy; public uint mouseData; public uint dwFlags; public uint time; public IntPtr dwExtraInfo; } [StructLayout(LayoutKind.Sequential)] public struct KEYBDINPUT { public ushort wVk; public ushort wScan; public uint dwFlags; public uint time; public IntPtr dwExtraInfo; } [StructLayout(LayoutKind.Sequential)] public struct HARDWAREINPUT { public int uMsg; public short wParamL; public short wParamH; } [StructLayout(LayoutKind.Explicit)] public struct MOUSEKEYBDHARDWAREINPUT { [FieldOffset(0)] public MOUSEINPUT mi; [FieldOffset(0)] public KEYBDINPUT ki; [FieldOffset(0)] public HARDWAREINPUT hi; } [StructLayout(LayoutKind.Sequential)] public struct INPUT { public int type; public MOUSEKEYBDHARDWAREINPUT mkhi; } 

}

一个WM_LBUTTONDOWN事件后程序输出:

 In hook. Extra info doesn't match. hookStruct.dwExtraInfo: 0 Received WM_INPUT. rawInput.extraInfo: 0 Creating local mouse event. Return value of SendInput: 1 Received WM_INPUT. rawInput.extraInfo: 1000 

你有没有尝试SendMessage(this.Handle,WM _…?