如何在C#中正确使用SendInput()模拟鼠标输入

4
我尝试使用C# .NET中的user32 dll中的SendInput()模拟(全局)鼠标点击。我已经尝试过使用SendInput()进行键盘输入,它可以正常工作。但由于某些原因,它无法用于鼠标输入。
以下是我的代码:
为了简单起见,我没有放置KEYBDINPUT和HARDWAREINPUT(结构体)的定义,因为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等),但目前仍未见效。


“nothing worked so far” 这句话并不是一个问题陈述。请参考[ask]。 - IInspectable
1个回答

2

对于internal long dx;dy,我在我的struct MOUSEINPUT中使用了int类型。

根据MOUSEINPUT文档dxdyLONG类型。

但是,在C++中,LONG至少是32位,而在C#中,long是64位。因此,它与C#的int匹配。(详细信息

[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 不起作用呢? 根据文档MOUSEINPUT.time 用于事件的时间戳。 我认为这是在每个输入被处理之前的时间延迟,或者它还有其他含义吗? - Fahim Mahbub
@FahimMahbub 我没有测试过这个。我知道对于键盘输入,当我使用单个SendInput调用发送批量输入时,它会有内置的延迟。也许这个延迟时间是相对的,并且只在你在INPUT[]数组中发送多个输入项时起作用。 - aepot
@aepot 你不能使用time字段来实际延迟。那不是它的用途。相反,你需要在SendInput调用之间插入实际的延迟。 - Remy Lebeau
@RemyLebeau 感谢你的纠正。那只是一个猜测,我没有尝试过。 - aepot
3
当你使用SendInput合成输入时,你同时也在合成时间戳。 - IInspectable

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接