如何在 c# 控制台应用程序中跟踪和 read/write 鼠标移动

How can I track and read/write Mouse movement in c# Console App

所以我制作了一个程序来跟踪一个名为 Rust 的游戏的鼠标移动,我制作这个程序来跟踪枪支中的喷射模式等。我制作并且它有效,除了它只跟踪屏幕上的位置而不是实际移动在 Rust 这样的游戏中,鼠标总是居中,所以没用。我到处寻找我能想到的每个搜索标题,但找不到任何东西。跟踪 returns X 和 Y 坐标的鼠标移动的最佳方法是什么?

TL:DR 我制作了一个程序,它可以工作,但是方法不对,跟踪 returns X 和 Y 坐标的鼠标移动的最佳方法是什么?

如果需要,这里是代码:

using System;
using Timer = System.Timers.Timer;
using System.Timers;
using System.Windows.Forms;
using System.Drawing;
using System.Threading;
using Gma.System.MouseKeyHook;
using System.IO;
using System.Collections.Generic;
using Newtonsoft.Json;

namespace MouseTrackerConsole
{
    class Program
    {
        private static List<Coords> QuickCoords = new List<Coords>();
        private static int fileNumber = 0;
        private static Rectangle screenResolution = Screen.PrimaryScreen.Bounds;
        private static IKeyboardMouseEvents HookEvents = null;
        private static Timer loopTimer;

        [STAThread]
        static void Main(string[] args)
        {
            DirectoryInfo di = new DirectoryInfo("Spray");

            foreach (FileInfo file in di.GetFiles())
            {
                file.Delete();
            }

            loopTimer = new Timer();
            loopTimer.Interval = 100;
            loopTimer.Enabled = false;
            loopTimer.Elapsed += loopTimerEvent;
            loopTimer.AutoReset = true;

            if(!Directory.Exists("Spray"))
            {
                Directory.CreateDirectory("Spray");
            }

            Hook.GlobalEvents().MouseDown += async (sender, e) =>
            {
                if (e.Button == MouseButtons.Left)
                {
                    Thread.Sleep(100);
                    loopTimer.Enabled = true;
                }
            };

            Hook.GlobalEvents().MouseUp += async (sender, e) =>
            {
                if (e.Button == MouseButtons.Left)
                {
                    loopTimer.Enabled = false;
                    if (QuickCoords.Count == 0)
                    {

                    }
                    else 
                    {
                        using (StreamWriter file = File.CreateText($@"Spray\Spray{fileNumber}.akspray"))
                        {
                            JsonSerializer serializer = new JsonSerializer();
                            serializer.Serialize(file, QuickCoords);
                        }
                        QuickCoords.Clear();
                        fileNumber += 1;
                        Console.WriteLine(fileNumber);
                    }
                    
                }
            };
            try
            {
                Application.Run(new ApplicationContext());
            }
            catch (AccessViolationException)
            {
                Environment.Exit(0);
            }
        }
        private static void loopTimerEvent(Object source, ElapsedEventArgs e)
        {
            Console.WriteLine("x: " + Cursor.Position.X + " y: " + Cursor.Position.Y);
            QuickCoords.Add(new Coords { X = Cursor.Position.X.ToString(), Y = Cursor.Position.Y.ToString() });
        }
    }

    internal class Coords
    {
        public string X { get; set; }
        public string Y { get; set; }
    }
}

提前致谢

可以使用 Pinvoke。 The solution here 是一个开始,但它可能仍然被前台应用程序捕获并且永远不会报告给您的应用程序。

如果是这样,您可以使用另一个 winapi Pinvoke,SetWindowsHooksEx,像这样:

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetWindowsHookEx(HookType hookType, HookProc lpfn, IntPtr hMod, uint dwThreadId);

您仍然需要做一些工作来设置 winapi 结构和挂钩的回调,但是这里有一个很好的例子来说明如何设置它:Using windows hooks with C# and P/Invoke

重要的部分是:

[UnmanagedFunctionPointer(CallingConvention.Winapi)]
internal delegate IntPtr HookProc(int nCode, UIntPtr wParam, IntPtr lParam);

[StructLayout(LayoutKind.Sequential)]
internal struct MouseLowLevelHookStruct
{
    public Point pt;
    public int mouseData;
    public int flags;
    public int time;
    public IntPtr dwExtraInfo;
}

然后就是使用适当的回调设置你的钩子并将 lParam 编组到 MouseLowLevelHookStruct。

编辑:我查看了您正在使用的 MouseKeyHook nuget 包,它似乎在幕后调用了我上面提到的 winapi 方法。我无法通过控制台应用程序使其正常工作,但在 winform 应用程序中,以下内容可以很好地捕获所有鼠标移动:

Gma.System.MouseKeyHook.Hook.GlobalEvents().MouseMoveExt += Form1_MouseMoveExt;

它甚至将鼠标光标移出屏幕的尝试报告为负数,因此它似乎能够报告来自保持鼠标捕获的应用程序的事件。除非你有充分的理由想要坚持使用控制台应用程序,否则最简单的方法就是切换到 winforms 并使用该事件处理程序。