简体   繁体   English

WH_MOUSE_LL注入的事件(mouse_event,SendInput)未调用挂钩

[英]WH_MOUSE_LL Hook doesn't get called for injected events (mouse_event, SendInput)

My code uses a WH_MOUSE_LL hook to initially suppress all mouse input, unless the dwExtraInfo property is set to a certain value. 我的代码使用WH_MOUSE_LL钩子最初禁止所有鼠标输入,除非dwExtraInfo属性设置为某个值。 The program is also registered for raw input for mouse devices, so that I can identify which device is responsible for the input. 该程序还注册了鼠标设备的原始输入,因此我可以确定哪个设备负责输入。 When I get a WM_INPUT message and determine the source, depending on the device I might just want to allow the event to take effect, in which case I recreate it with SendInput (tried mouse_event, which has been superseded, as well), providing data in the dwExtraInfo property. 当我收到WM_INPUT消息并确定源时,取决于设备,我可能只想允许事件生效,在这种情况下,我使用SendInput(也尝试过mouse_event,也已取代)重新创建了事件,并提供了数据在dwExtraInfo属性中。 The idea is that the hook should then see this new injected event, see the extra info and not suppress it. 这个想法是钩子然后应该看到这个新的注入事件,看到额外的信息而不是抑制它。 Unfortunately, the injected event is never seen by the hook. 不幸的是,注入事件从未被钩子看到。 The corresponding WM_INPUT message is seen by the window procedure though and SendInput returns 1, so it seems that the event is being generated. 尽管窗口过程可以看到相应的WM_INPUT消息,并且SendInput返回1,所以似乎正在生成该事件。 I have read that the context switches to the thread that installed the hook and that it must have a message loop. 我已经读到上下文将切换到安装该挂钩的线程,并且它必须具有消息循环。 I believe my code meets that qualification (Since Application.Run() starts a message loop on the thread - I've also tried a handwritten Win32-style message loop in its place). 我相信我的代码符合该条件(因为Application.Run()在线程上启动了消息循环-我也尝试过在其位置执行手写Win32样式的消息循环)。 Anyone have any ideas why this is happening and/or how to fix this? 任何人都知道为什么会这样和/或如何解决这个问题?

The following code exhibits the problem. 以下代码显示了该问题。 It should run with references to System and System.Windows.Forms. 它应在对System和System.Windows.Forms的引用下运行。

Main class: 主班:

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 class: 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);
}

Additional P/Invoke structs, enums, etc. 其他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;
    }

} }

Program output after one WM_LBUTTONDOWN event: 一个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 _...?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM