You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多屏环境下C#模拟鼠标点击仅首次生效问题修复咨询

问题修复方案

核心问题分析

你的代码里有几个关键错误导致仅第一次点击有效:

  1. 错误保存鼠标原始位置:oldPos被硬编码成目标坐标(-850,35),第一次点击后鼠标被强制移到这个位置,后续操作时光标位置没有变化,系统可能判定无有效交互。
  2. SendInput事件未绑定目标坐标:仅移动光标后模拟点击,依赖系统即时更新光标位置,多屏环境下容易出现同步问题,导致后续点击失效。
  3. 冗余代码干扰逻辑:调用了ClientToScreen但未使用转换后的坐标,属于无效代码。

修复后的完整代码

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

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

    internal struct INPUT
    {
        public UInt32 Type;
        public MOUSEKEYBDHARDWAREINPUT Data;
    }

    [StructLayout(LayoutKind.Explicit)]
    internal struct MOUSEKEYBDHARDWAREINPUT
    {
        [FieldOffset(0)]
        public MOUSEINPUT Mouse;
    }

    internal struct MOUSEINPUT
    {
        public int X;
        public int Y;
        public uint MouseData;
        public uint Flags;
        public uint Time;
        public IntPtr ExtraInfo;
    }

    // 鼠标事件常量
    private const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
    private const uint MOUSEEVENTF_LEFTUP = 0x0004;
    private const uint MOUSEEVENTF_ABSOLUTE = 0x8000;

    public static void ClickOnPoint()
    {
        // 保存当前鼠标真实位置
        var oldPos = Cursor.Position;
        // 目标屏幕坐标(多屏环境下的虚拟坐标)
        var targetPos = new Point(-850, 35);

        try
        {
            // 将目标坐标转换为SendInput需要的绝对坐标范围(0-65535)
            int absoluteX = (targetPos.X * 65535) / Screen.PrimaryScreen.Bounds.Width;
            int absoluteY = (targetPos.Y * 65535) / Screen.PrimaryScreen.Bounds.Height;

            // 构建鼠标按下事件(带绝对坐标)
            var inputMouseDown = new INPUT
            {
                Type = 0 // 0表示鼠标事件
            };
            inputMouseDown.Data.Mouse.X = absoluteX;
            inputMouseDown.Data.Mouse.Y = absoluteY;
            inputMouseDown.Data.Mouse.Flags = MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_ABSOLUTE;

            // 构建鼠标抬起事件(带绝对坐标)
            var inputMouseUp = new INPUT
            {
                Type = 0
            };
            inputMouseUp.Data.Mouse.X = absoluteX;
            inputMouseUp.Data.Mouse.Y = absoluteY;
            inputMouseUp.Data.Mouse.Flags = MOUSEEVENTF_LEFTUP | MOUSEEVENTF_ABSOLUTE;

            // 发送输入事件
            var inputs = new[] { inputMouseDown, inputMouseUp };
            SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));
        }
        finally
        {
            // 无论是否成功,都恢复鼠标原始位置
            Cursor.Position = oldPos;
        }
    }
}

关键修改说明

  • 修复鼠标位置保存:把oldPos改为Cursor.Position,确保每次执行都保存当前真实的鼠标位置,执行完成后准确恢复。
  • 绑定绝对坐标到SendInput:将目标屏幕坐标转换为SendInput要求的0-65535范围,并添加MOUSEEVENTF_ABSOLUTE标志,直接指定点击位置,不再依赖光标位置的同步,避免多屏环境下的失效问题。
  • 移除冗余代码:删掉无用的ClientToScreen调用,简化函数参数(因为不需要传入窗口句柄和客户端坐标,直接使用屏幕坐标)。
  • 添加异常处理:用try-finally确保鼠标位置一定会被恢复,避免操作失败后鼠标停留在目标位置。

使用提示

你的F11快捷键触发逻辑中,直接调用ClickOnPointTool.ClickOnPoint()即可,不需要再传入额外参数。

内容的提问来源于stack exchange,提问作者Sarper Sözen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 02:32:48