gpt4 book ai didi

c# - SendInput 不执行单击鼠标按钮,除非我移动光标

转载 作者:IT王子 更新时间:2023-10-29 04:27:27 24 4
gpt4 key购买 nike

除非我移动光标,否则 SendInput 不会执行单击鼠标按钮。

我将不胜感激这方面的帮助,因为我似乎无法理解它。

我有一个在前景窗口上执行鼠标单击的程序,我在其中使用 SendInput 来模拟鼠标左键单击。问题是,如果我将光标移动到单击位置,则 SendInput 将进行单击,但是如果我不移动光标,则即使通过 x 和 y 指向 MouseInputData 也不会发生单击。我想在根本不需要实际移动光标的情况下执行鼠标左键单击。

波纹管是我的类(class)(相当简单明了)

namespace StackSolution.Classes
{
public static class SendInputClass
{

[DllImport("user32.dll", SetLastError = true)]
static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize);

[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetCursorPos(out Point lpPoint);



[StructLayout(LayoutKind.Sequential)]
struct INPUT
{
public SendInputEventType type;
public MouseKeybdhardwareInputUnion mkhi;
}
[StructLayout(LayoutKind.Explicit)]
struct MouseKeybdhardwareInputUnion
{
[FieldOffset(0)]
public MouseInputData mi;

[FieldOffset(0)]
public KEYBDINPUT ki;

[FieldOffset(0)]
public HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public int uMsg;
public short wParamL;
public short wParamH;
}
struct MouseInputData
{
public int dx;
public int dy;
public uint mouseData;
public MouseEventFlags dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[Flags]
enum MouseEventFlags : uint
{
MOUSEEVENTF_MOVE = 0x0001,
MOUSEEVENTF_LEFTDOWN = 0x0002,
MOUSEEVENTF_LEFTUP = 0x0004,
MOUSEEVENTF_RIGHTDOWN = 0x0008,
MOUSEEVENTF_RIGHTUP = 0x0010,
MOUSEEVENTF_MIDDLEDOWN = 0x0020,
MOUSEEVENTF_MIDDLEUP = 0x0040,
MOUSEEVENTF_XDOWN = 0x0080,
MOUSEEVENTF_XUP = 0x0100,
MOUSEEVENTF_WHEEL = 0x0800,
MOUSEEVENTF_VIRTUALDESK = 0x4000,
MOUSEEVENTF_ABSOLUTE = 0x8000
}
enum SendInputEventType : int
{
InputMouse,
InputKeyboard,
InputHardware
}

public static void ClickLeftMouseButton(int x, int y)
{
INPUT mouseInput = new INPUT();
mouseInput.type = SendInputEventType.InputMouse;
mouseInput.mkhi.mi.dx = x;
mouseInput.mkhi.mi.dy = y;
mouseInput.mkhi.mi.mouseData = 0;

//getting current cursor location
Point p;
if (GetCursorPos(out p))
SetCursorPos(x, y);


mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTDOWN;
SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));

mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTUP;
SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));

//returning cursor to previous position
SetCursorPos(p.X, p.Y);
}
}
}

如果我像这样删除获取光标位置,则相同的 ClickLeftMouseButton 函数将不会单击。

   public static void ClickLeftMouseButton(int x, int y)
{
INPUT mouseInput = new INPUT();
mouseInput.type = SendInputEventType.InputMouse;
mouseInput.mkhi.mi.dx = x;
mouseInput.mkhi.mi.dy = y;
mouseInput.mkhi.mi.mouseData = 0;


mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTDOWN;
SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));

mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTUP;
SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));
}

提前谢谢你。

最佳答案

在使用 SendInput 函数时,您应该考虑一些事项。

如果您没有指定 MOUSEEVENTF_ABSOLUTE 标志,则 dxdy(MouseInputData 结构)是相对于当前鼠标位置的坐标。如果您确实指定了 MOUSEEVENTF_ABSOLUTE,则 dxdy 是 0 到 65535 之间的绝对坐标。因此,如果您的 x 和 y 坐标是屏幕坐标,您应该使用以下函数计算 dxdy:

enum SystemMetric
{
SM_CXSCREEN = 0,
SM_CYSCREEN = 1,
}

[DllImport("user32.dll")]
static extern int GetSystemMetrics(SystemMetric smIndex);

int CalculateAbsoluteCoordinateX(int x)
{
return (x * 65536) / GetSystemMetrics(SystemMetric.SM_CXSCREEN);
}

int CalculateAbsoluteCoordinateY(int y)
{
return (y * 65536) / GetSystemMetrics(SystemMetric.SM_CYSCREEN);
}

此外,在通过 SendInput 发送 MOUSEDOWN 和 MOUSEUP 事件之前,您必须将鼠标移动到要单击的控件上:

public static void ClickLeftMouseButton(int x, int y)
{
INPUT mouseInput = new INPUT();
mouseInput.type = SendInputEventType.InputMouse;
mouseInput.mkhi.mi.dx = CalculateAbsoluteCoordinateX(x);
mouseInput.mkhi.mi.dy = CalculateAbsoluteCoordinateY(y);
mouseInput.mkhi.mi.mouseData = 0;


mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_MOVE |MouseEventFlags.MOUSEEVENTF_ABSOLUTE;
SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));

mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTDOWN;
SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));

mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTUP;
SendInput(1, ref mouseInput, Marshal.SizeOf(new INPUT()));
}

以上代码假定xy 是屏幕像素坐标。您可以使用以下代码计算 winform 上按钮(目标)的坐标:

 Point screenCoordsCentre=
button1.PointToScreen(new Point(button1.Width/2, button1.Height/2));

希望这对您有所帮助。

关于c# - SendInput 不执行单击鼠标按钮,除非我移动光标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8021954/

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