WH_MOUSE_LL没有为注入事件调用Hook(mouse_event,SendInput)

时间:2010-02-01 03:29:58

标签: c# windows hook mouseevent sendinput

我的代码使用WH_MOUSE_LL挂钩来初始禁止所有鼠标输入,除非将dwExtraInfo属性设置为某个值。该程序还注册了鼠标设备的原始输入,以便我可以识别哪个设备负责输入。当我收到WM_INPUT消息并确定源时,根据设备我可能只想让事件生效,在这种情况下,我使用SendInput重新创建它(尝试了mouse_event,它已被取代),提供数据在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

1 个答案:

答案 0 :(得分:-1)

您是否尝试过SendMessage(this.Handle,WM _...?