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

游戏场景鼠标减速代码实现及失效问题修复咨询

解决游戏中鼠标速度无法降低的问题

问题原因

你的代码通过SystemParametersInfo修改系统鼠标速度,但多数游戏会直接读取原始鼠标硬件输入(如Raw Input/DirectInput),完全绕过系统的鼠标速度缩放逻辑,导致系统层面的设置无法影响游戏内的鼠标移动。

修复方案

使用**低级全局鼠标钩子(LowLevelMouseHook)**拦截所有鼠标移动事件,手动调整鼠标的位移量,这种方式可以覆盖包括游戏在内的所有场景,因为它直接处理硬件级的鼠标输入。

修改后的完整代码

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

namespace MouseSpeedDesktop
{
    public partial class Form1 : Form
    {
        // 钩子相关常量
        private const int WH_MOUSE_LL = 14;
        private const int WM_MOUSEMOVE = 0x0200;

        // 钩子句柄
        private IntPtr _mouseHookHandle = IntPtr.Zero;
        // 减速标志
        private bool _isSpeedReduced = false;
        // 减速比例(比如设为0.3,就是原始速度的30%)
        private readonly float _speedReductionFactor = 0.3f;
        // 原始鼠标速度备份(用于恢复)
        private int _originalMouseSpeed;

        // 鼠标钩子结构体
        [StructLayout(LayoutKind.Sequential)]
        private struct MSLLHOOKSTRUCT
        {
            public POINT pt;
            public uint mouseData;
            public uint flags;
            public uint time;
            public IntPtr dwExtraInfo;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct POINT
        {
            public int x;
            public int y;
        }

        // 导入钩子API
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);

        // 系统鼠标速度相关API(用于备份原始速度)
        private const UInt32 SPI_GETMOUSESPEED = 0x0070;
        private const UInt32 SPI_SETMOUSESPEED = 0x0071;

        [DllImport("User32.dll")]
        private static extern Boolean SystemParametersInfo(
            UInt32 uiAction,
            UInt32 uiParam,
            IntPtr pvParam,
            UInt32 fWinIni);

        // 钩子回调委托
        private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
        private LowLevelMouseProc _mouseProc;

        public Form1()
        {
            InitializeComponent();
            // 备份原始鼠标速度
            IntPtr speedPtr = Marshal.AllocHGlobal(4);
            SystemParametersInfo(SPI_GETMOUSESPEED, 0, speedPtr, 0);
            _originalMouseSpeed = Marshal.ReadInt32(speedPtr);
            Marshal.FreeHGlobal(speedPtr);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // 注册全局鼠标钩子
            _mouseProc = MouseHookCallback;
            using (var curProcess = System.Diagnostics.Process.GetCurrentProcess())
            using (var curModule = curProcess.MainModule)
            {
                _mouseHookHandle = SetWindowsHookEx(WH_MOUSE_LL, _mouseProc, GetModuleHandle(curModule.ModuleName), 0);
            }
            // 注册键盘钩子(用于触发减速/恢复)
            HookManager.KeyDown += KeyPressed;
            HookManager.KeyUp += KeyRemoved;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            // 释放钩子
            UnhookWindowsHookEx(_mouseHookHandle);
            // 恢复原始鼠标速度
            SystemParametersInfo(SPI_SETMOUSESPEED, 0, new IntPtr(_originalMouseSpeed), 0);
            // 注销键盘钩子
            HookManager.KeyDown -= KeyPressed;
            HookManager.KeyUp -= KeyRemoved;
        }

        private void KeyPressed(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Q)
            {
                _isSpeedReduced = true;
            }
        }

        private void KeyRemoved(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Q)
            {
                _isSpeedReduced = false;
            }
        }

        private IntPtr MouseHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && wParam == (IntPtr)WM_MOUSEMOVE && _isSpeedReduced)
            {
                var hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
                // 获取当前光标位置并按比例调整位移
                Cursor.Position = new System.Drawing.Point(
                    Cursor.Position.X + (int)((hookStruct.pt.x - Cursor.Position.X) * _speedReductionFactor),
                    Cursor.Position.Y + (int)((hookStruct.pt.y - Cursor.Position.Y) * _speedReductionFactor)
                );
                // 返回非0值拦截原始鼠标事件,避免重复移动
                return (IntPtr)1;
            }
            // 传递事件给下一个钩子
            return CallNextHookEx(_mouseHookHandle, nCode, wParam, lParam);
        }
    }
}

关键说明

  1. 钩子拦截逻辑:通过LowLevelMouseHook捕获所有鼠标移动事件,当_isSpeedReduced为true时,按比例缩放鼠标位移,手动设置光标位置并拦截原始事件,避免重复移动。
  2. 原始速度备份:程序启动时备份系统原始鼠标速度,退出时自动恢复,避免遗留设置影响日常使用。
  3. 减速比例调整:修改_speedReductionFactor的值可以调整减速程度,比如0.2就是原始速度的20%,数值越小速度越慢。

注意事项

  • 必须以管理员权限运行程序,否则可能无法拦截游戏的鼠标输入。
  • 部分反作弊系统可能会检测全局钩子,使用前请确认游戏的反作弊政策,避免账号风险。
  • 确保程序退出时正确释放钩子,否则可能导致系统鼠标异常(重启系统也可恢复)。

内容的提问来源于stack exchange,提问作者Victor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 02:15:02