【问题标题】:How to use SendInput() properly to simulate mouse input in C#如何正确使用 SendInput() 在 C# 中模拟鼠标输入
【发布时间】:2020-11-07 18:30:51
【问题描述】:

我试图在 C# .NET 中使用 user32 dll 中的 SendInput() 模拟(全局)鼠标点击。 我已经尝试过使用 SendInput() 进行键盘输入,并且效果很好。但由于某些原因,它不适用于鼠标输入。

这是我的代码,

为简单起见,我没有给出 KEYBDINPUT 和 HARDWAREINPUT (struct) 的定义。因为 MOUSEINPUT 仅在此处相关。

    [DllImport("user32.dll")]
    internal static extern uint SendInput(uint nInputs,  [MarshalAs(UnmanagedType.LPArray), In] INPUT[] pInputs, int cbSize);

    //main calling method
    public static void CLICK()
    {
        INPUT []i = new INPUT[1];

        i[0].type = 0;
        i[0].U.mi.time = 0;
        i[0].U.mi.dwFlags = MOUSEEVENTF.LEFTDOWN | MOUSEEVENTF.ABSOLUTE;
        i[0].U.mi.dwExtraInfo = UIntPtr.Zero;
        i[0].U.mi.dx = 1;
        i[0].U.mi.dy = 1;

        SendInput(1, i, INPUT.Size);
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct INPUT
    {
        internal uint type;
        internal InputUnion U;
        internal static int Size
        {
            get { return Marshal.SizeOf(typeof(INPUT)); }
        }
    }

    [StructLayout(LayoutKind.Explicit)]
    internal struct InputUnion
    {
        [FieldOffset(0)]
        internal MOUSEINPUT mi;
        [FieldOffset(0)]
        internal KEYBDINPUT ki;
        [FieldOffset(0)]
        internal HARDWAREINPUT hi;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct MOUSEINPUT
    {
        internal long dx;
        internal long dy;
        internal int mouseData;
        internal MOUSEEVENTF dwFlags;
        internal uint time;
        internal UIntPtr dwExtraInfo;
    }

    [Flags]
    internal enum MOUSEEVENTF : uint
    {
        ABSOLUTE = 0x8000,
        HWHEEL = 0x01000,
        MOVE = 0x0001,
        MOVE_NOCOALESCE = 0x2000,
        LEFTDOWN = 0x0002,
        LEFTUP = 0x0004,
        RIGHTDOWN = 0x0008,
        RIGHTUP = 0x0010,
        MIDDLEDOWN = 0x0020,
        MIDDLEUP = 0x0040,
        VIRTUALDESK = 0x4000,
        WHEEL = 0x0800,
        XDOWN = 0x0080,
        XUP = 0x0100
    }

另外,我为 x,y 尝试了不同的点。以及其他 dwFlags(例如 LEFTUP、MOVE..),但到目前为止没有任何效果。

【问题讨论】:

  • “到目前为止没有任何效果” 不是问题陈述。见How to Ask

标签: c# .net wpf winapi user32


【解决方案1】:

对于internal long dx;dy,我有int 输入我的struct MOUSEINPUT

根据MOUSEINPUT documentationdxdyLONG

但是 C++ 中的 LONG“至少”是 32 位,而 C# 中的 long 是 64 位。因此它匹配 C#int。 (details)

[StructLayout(LayoutKind.Sequential)]
internal struct MOUSEINPUT
{
    internal int dx;
    internal int dy;
    internal int mouseData;
    internal MOUSEEVENTF dwFlags;
    internal uint time;
    internal UIntPtr dwExtraInfo;
}

【讨论】:

  • 这有效,但您知道为什么 MOUSEINPUT.time / KEYBDINPUT.time 不起作用吗?根据documentationMOUSEINPUT.time 用于事件的时间戳。我认为这是在处理每个输入之前的时间延迟。还是还有别的意思?
  • @FahimMahbub 我没有测试过。我知道对于键盘,当我发送批量输入时它具有嵌入式延迟,例如通过单个 SendInput 调用修改了击键。也许这个延迟时间是相对的,并且仅当您在INPUT[] 数组中发送多个输入项时才有效。
  • @aepot 您不能使用time 字段来导致实际延迟。这不是它的本意。您需要在 SendInput 调用之间设置实际延迟
  • @RemyLebeau 感谢您的指正。这是一个猜测,我没有尝试。
猜你喜欢
  • 1970-01-01
  • 2015-10-15
  • 2011-06-05
  • 2018-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-05
  • 1970-01-01
相关资源
最近更新 更多