0

So I made a program that tracks mouse movement for a game called rust, I made this to track spray patterns in guns and etc. I made and it works except for it only tracks the position on screen and not actual movement and in a game like rust, the mouse is always centered so it's useless. I looked everywhere with every search title I could think of and couldn't find anything. what is the best way to track mouse movement that returns X and Y coordinates?

TL:DR I made a program and it works but the wrong way, what is the best way to track mouse movement that returns X and Y coordinates?

here is the code if needed:

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; }
    }
}

thank you in advance

Norzka
  • 47
  • 3
  • 10

1 Answers1

1

It is possible to do using Pinvoke. The solution here is a start, but it may still be captured by the foreground application and never reported to your application.

If that's the case, you can use another winapi Pinvoke, SetWindowsHooksEx, like so:

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

You'd still have to do some legwork setting up the winapi structs and the callback for the hook, but there's a pretty good example of how to set it up here: Using windows hooks with C# and P/Invoke

The important parts are:

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

and

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

Then it's a matter of setting up your hook with an appropriate callback and marshaling lParam to MouseLowLevelHookStruct.

Edit: I took a look at the MouseKeyHook nuget package you're using, and it seems behind the scenes it's calling the winapi methods I mentioned above. I couldn't get it to work appropriately from a console app, but in a winform app the following captured all mouse movement just fine:

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

It even reported attempts to move the mouse cursor off the screen as negative numbers, so it seems likely it will be able to report events from an application that keeps the mouse captive. Unless you have a very good reason to want to stick with a console app, it'd be easiest to just switch to winforms and use that event handler.

Rezer
  • 54
  • 5