gpt4 book ai didi

c# - WH_MOUSE_LL Hook 不会为注入(inject)的事件(mouse_event、SendInput)调用

转载 作者:可可西里 更新时间:2023-11-01 14:37:47 35 4
gpt4 key购买 nike

我的代码使用 WH_MOUSE_LL Hook 来最初抑制所有鼠标输入,除非 dwExtraInfo 属性设置为特定值。该程序还注册了鼠标设备的原始输入,因此我可以识别哪个设备负责输入。当我收到 WM_INPUT 消息并确定源时,根据设备我可能只想让事件生效,在这种情况下我用 SendInput 重新创建它(尝试过 mouse_event,它也已被取代),提供数据在 dwExtraInfo 属性中。这个想法是 Hook 应该看到这个新的注入(inject)事件,看到额外的信息而不是抑制它。不幸的是,注入(inject)的事件永远不会被钩子(Hook)看到。尽管窗口过程看到相应的 WM_INPUT 消息,但 SendInput 返回 1,因此似乎正在生成事件。我读到上下文切换到安装钩子(Hook)的线程并且它必须有一个消息循环。我相信我的代码符合该条件(因为 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);
}

输入处理器类:

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_... 吗?

关于c# - WH_MOUSE_LL Hook 不会为注入(inject)的事件(mouse_event、SendInput)调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2174512/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com