首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在c#控制台应用程序中跟踪和读写鼠标运动

如何在c#控制台应用程序中跟踪和读写鼠标运动
EN

Stack Overflow用户
提问于 2021-02-17 02:58:05
回答 1查看 419关注 0票数 0

所以我制作了一个程序,用来跟踪游戏中的鼠标动作,叫做铁锈。我制作了这个程序来跟踪枪械上的喷雾图案等等。我制作了这个程序,除了它只跟踪屏幕上的位置,而不是实际的移动。在像铁锈这样的游戏中,鼠标总是以中心为中心,所以它是无用的。我到处找,我能想到的每一个搜索标题都找不到任何东西。跟踪返回X和Y坐标的鼠标运动的最佳方法是什么?

TL:I博士做了一个程序,它的工作方式,但错误的方式,什么是最好的方式跟踪鼠标运动返回X和Y坐标?

如果需要的话,下面是代码:

代码语言:javascript
运行
复制
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; }
    }
}

先谢谢你

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-17 10:08:19

使用Pinvoke是可能的。这里的解决方案是一个开始,但前台应用程序仍可能捕获它,并且从未向您的应用程序报告。

如果是这样的话,您可以使用另一个winapi调用,SetWindowsHooksEx,如下所示:

代码语言:javascript
运行
复制
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetWindowsHookEx(HookType hookType, HookProc lpfn, IntPtr hMod, uint dwThreadId);

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

重要的部分是:

代码语言:javascript
运行
复制
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
internal delegate IntPtr HookProc(int nCode, UIntPtr wParam, IntPtr lParam);

代码语言:javascript
运行
复制
[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应用程序中,下面的鼠标动作都很好:

代码语言:javascript
运行
复制
Gma.System.MouseKeyHook.Hook.GlobalEvents().MouseMoveExt += Form1_MouseMoveExt;

它甚至报告了试图将鼠标光标从屏幕上移出屏幕的负数,因此它很可能能够报告来自一个应用程序的事件,该应用程序使鼠标无法被捕获。除非您有一个非常好的理由来坚持使用控制台应用程序,否则只需切换到winforms并使用该事件处理程序就更容易了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66235128

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档