c#实现鼠标mousemove事件抽稀,避免大数据阻塞网络

这个封装类可以独立于具体的网络传输逻辑,为任何需要减少鼠标移动数据量的应用提供灵敏度和数据量优化。

核心优化功能

1. 灵敏度调整

csharp 复制代码
// 减少微小移动的数据发送
(2, 1) × 0.5 → (1, 0) // 忽略微小移动

2. 移动累积

csharp 复制代码
// 累积多次小移动,批量发送
(1, 0) + (1, 1) + (0, 1) → (2, 2) // 减少3次发送为1次

3. 阈值过滤

csharp 复制代码
// 忽略低于阈值的移动
(1, 0) → 忽略 // 如果阈值=2

4. 统计监控

csharp 复制代码
// 实时监控优化效果
// 接收1000事件,发送300事件,过滤率70%

工作流程

复制代码
// ==================== 主处理流程 ====================
函数 处理鼠标移动(原始dx, 原始dy):
    总事件数++
    
    // 1. 灵敏度调整阶段
    (调整dx, 调整dy) = 应用灵敏度乘数(原始dx, 原始dy)
    
    // 2. 阈值检查阶段
    如果 (调整dx和dy都小于阈值 且 不要求立即发送):
        如果 (启用累积模式):
            累积移动量(调整dx, 调整dy)  // 先存起来不发送
            返回 空                  // 此次不发送数据
        否则:
            返回 空                  // 直接丢弃微小移动
    否则:
        // 3. 准备发送阶段
        (最终dx, 最终dy) = 获取最终移动量(调整dx, 调整dy)
        
        如果 (最终dx和dy都为0):
            返回 空                  // 没有实际移动
        否则:
            发送事件数++
            返回 (最终dx, 最终dy)     // 发送优化后的数据

// ==================== 灵敏度调整 ====================
函数 应用灵敏度乘数(dx, dy):
    如果 (灵敏度乘数 ≈ 1.0):
        返回 (dx, dy)               // 不做调整
    
    新dx = 四舍五入(dx × 乘数)
    新dy = 四舍五入(dy × 乘数)
    
    // 确保不丢失移动方向
    如果 (dx ≠ 0 且 新dx = 0): 新dx = 符号(dx)
    如果 (dy ≠ 0 且 新dy = 0): 新dy = 符号(dy)
    
    返回 (新dx, 新dy)

// ==================== 移动累积 ====================
函数 累积移动量(dx, dy):
    累积x += dx
    累积y += dy
    
    // 防止累积过大(避免延迟感)
    累积x = 限制范围(累积x, -最大累积值, 最大累积值)
    累积y = 限制范围(累积y, -最大累积值, 最大累积值)

// ==================== 获取最终移动量 ====================
函数 获取最终移动量(当前dx, 当前dy):
    最终dx = 当前dx + 累积x
    最终dy = 当前dy + 累积y
    
    重置累积()                      // 清空累积器
    返回 (最终dx, 最终dy)

// ==================== 强制发送 ====================
函数 强制发送所有累积():
    如果 (累积x ≠ 0 或 累积y ≠ 0):
        移动量 = (累积x, 累积y)
        重置累积()
        返回 移动量                 // 发送所有累积的移动
    否则:
        返回 空

以下是单独封装的鼠标灵敏度优化类:

csharp 复制代码
using System;
using System.Diagnostics;

/// <summary>
/// 鼠标灵敏度优化器 - 减少鼠标移动事件的数据发送量
/// </summary>
public class MouseSensitivityOptimizer
{
    private readonly double _sensitivityMultiplier;
    private int _accumulatedDx;
    private int _accumulatedDy;
    private readonly int _minMovementThreshold;
    private readonly int _maxAccumulation;
    private readonly bool _enableAccumulation;
    
    /// <summary>
    /// 灵敏度优化统计信息
    /// </summary>
    public class OptimizationStats
    {
        public int TotalEventsReceived { get; set; }
        public int TotalEventsSent { get; set; }
        public int EventsFiltered => TotalEventsReceived - TotalEventsSent;
        public double FilterRate => TotalEventsReceived > 0 ? (double)EventsFiltered / TotalEventsReceived : 0;
    }
    
    public OptimizationStats Stats { get; } = new OptimizationStats();
    
    /// <summary>
    /// 初始化鼠标灵敏度优化器
    /// </summary>
    /// <param name="sensitivityMultiplier">灵敏度乘数(0.5=减半,2.0=加倍)</param>
    /// <param name="minMovementThreshold">最小移动阈值(像素)</param>
    /// <param name="maxAccumulation">最大累积量(像素)</param>
    /// <param name="enableAccumulation">是否启用移动累积</param>
    public MouseSensitivityOptimizer(double sensitivityMultiplier = 1.0, 
                                    int minMovementThreshold = 1, 
                                    int maxAccumulation = 10,
                                    bool enableAccumulation = true)
    {
        _sensitivityMultiplier = Math.Clamp(sensitivityMultiplier, 0.1, 10.0);
        _minMovementThreshold = Math.Max(1, minMovementThreshold);
        _maxAccumulation = Math.Max(1, maxAccumulation);
        _enableAccumulation = enableAccumulation;
        
        Debug.WriteLine($"MouseSensitivityOptimizer initialized: " +
                       $"Multiplier={_sensitivityMultiplier:F2}, " +
                       $"Threshold={_minMovementThreshold}, " +
                       $"MaxAccumulation={_maxAccumulation}");
    }
    
    /// <summary>
    /// 从环境变量创建优化器(兼容DeskFlow设计)
    /// </summary>
    public static MouseSensitivityOptimizer FromEnvironmentVariable(string envVarName = "DESKFLOW_MOUSE_ADJUSTMENT")
    {
        double multiplier = 1.0;
        
        try
        {
            string envValue = Environment.GetEnvironmentVariable(envVarName);
            if (!string.IsNullOrEmpty(envValue))
            {
                if (double.TryParse(envValue, out double parsedValue))
                {
                    multiplier = Math.Clamp(parsedValue, 0.1, 10.0);
                    Debug.WriteLine($"Loaded sensitivity multiplier from {envVarName}: {multiplier:F2}");
                }
                else
                {
                    Debug.WriteLine($"Invalid {envVarName} value: {envValue}");
                }
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"Error reading environment variable {envVarName}: {ex.Message}");
        }
        
        return new MouseSensitivityOptimizer(multiplier);
    }
    
    /// <summary>
    /// 处理鼠标移动输入,返回优化后的移动量
    /// </summary>
    /// <param name="dx">原始X移动量</param>
    /// <param name="dy">原始Y移动量</param>
    /// <param name="sendImmediately">是否立即发送(忽略累积)</param>
    /// <returns>优化后的移动量,null表示应该忽略此次移动</returns>
    public (int dx, int dy)? ProcessMovement(int dx, int dy, bool sendImmediately = false)
    {
        Stats.TotalEventsReceived++;
        
        // 1. 应用灵敏度调整
        (int adjustedDx, int adjustedDy) = ApplySensitivityAdjustment(dx, dy);
        
        // 2. 检查是否低于阈值
        if (IsBelowThreshold(adjustedDx, adjustedDy) && !sendImmediately)
        {
            // 累积小幅度移动
            if (_enableAccumulation)
            {
                AccumulateMovement(adjustedDx, adjustedDy);
                return null; // 暂时不发送
            }
            else
            {
                // 不启用累积时,直接忽略微小移动
                return null;
            }
        }
        
        // 3. 获取最终要发送的移动量(包括累积值)
        (int finalDx, int finalDy) = GetFinalMovement(adjustedDx, adjustedDy);
        
        if (finalDx == 0 && finalDy == 0)
        {
            return null; // 没有实际移动
        }
        
        Stats.TotalEventsSent++;
        
        Debug.WriteLine($"Movement optimized: ({dx},{dy}) -> ({finalDx},{finalDy}) " +
                       $"[Filtered: {Stats.FilterRate:P0}]");
        
        return (finalDx, finalDy);
    }
    
    /// <summary>
    /// 强制发送所有累积的移动量
    /// </summary>
    public (int dx, int dy)? FlushAccumulatedMovement()
    {
        if (_accumulatedDx == 0 && _accumulatedDy == 0)
        {
            return null;
        }
        
        var movement = (_accumulatedDx, _accumulatedDy);
        ResetAccumulation();
        
        Stats.TotalEventsSent++;
        Debug.WriteLine($"Flushed accumulated movement: ({movement.dx},{movement.dy})");
        
        return movement;
    }
    
    /// <summary>
    /// 重置优化器状态(如屏幕切换时)
    /// </summary>
    public void Reset()
    {
        ResetAccumulation();
        Debug.WriteLine("Mouse sensitivity optimizer reset");
    }
    
    /// <summary>
    /// 应用灵敏度乘数
    /// </summary>
    private (int dx, int dy) ApplySensitivityAdjustment(int dx, int dy)
    {
        if (Math.Abs(_sensitivityMultiplier - 1.0) < 0.01)
        {
            return (dx, dy); // 无调整
        }
        
        int adjustedDx = (int)Math.Round(dx * _sensitivityMultiplier);
        int adjustedDy = (int)Math.Round(dy * _sensitivityMultiplier);
        
        // 确保至少保持原始方向
        if (dx != 0 && adjustedDx == 0) adjustedDx = Math.Sign(dx);
        if (dy != 0 && adjustedDy == 0) adjustedDy = Math.Sign(dy);
        
        return (adjustedDx, adjustedDy);
    }
    
    /// <summary>
    /// 检查移动量是否低于发送阈值
    /// </summary>
    private bool IsBelowThreshold(int dx, int dy)
    {
        return Math.Abs(dx) < _minMovementThreshold && 
               Math.Abs(dy) < _minMovementThreshold;
    }
    
    /// <summary>
    /// 累积移动量
    /// </summary>
    private void AccumulateMovement(int dx, int dy)
    {
        _accumulatedDx += dx;
        _accumulatedDy += dy;
        
        // 防止累积过大
        _accumulatedDx = Math.Clamp(_accumulatedDx, -_maxAccumulation, _maxAccumulation);
        _accumulatedDy = Math.Clamp(_accumulatedDy, -_maxAccumulation, _maxAccumulation);
    }
    
    /// <summary>
    /// 获取最终要发送的移动量(包括当前和累积值)
    /// </summary>
    private (int dx, int dy) GetFinalMovement(int currentDx, int currentDy)
    {
        int finalDx = currentDx + _accumulatedDx;
        int finalDy = currentDy + _accumulatedDy;
        
        ResetAccumulation();
        
        return (finalDx, finalDy);
    }
    
    /// <summary>
    /// 重置累积值
    /// </summary>
    private void ResetAccumulation()
    {
        _accumulatedDx = 0;
        _accumulatedDy = 0;
    }
}

// 使用示例
public class MouseSensitivityExample
{
    private readonly MouseSensitivityOptimizer _optimizer;
    
    public MouseSensitivityExample()
    {
        // 从环境变量创建或直接配置
        _optimizer = MouseSensitivityOptimizer.FromEnvironmentVariable();
        
        // 或者手动配置:
        // _optimizer = new MouseSensitivityOptimizer(
        //     sensitivityMultiplier: 0.7,  // 降低30%灵敏度
        //     minMovementThreshold: 2,     // 2像素以下不立即发送
        //     maxAccumulation: 8,          // 最大累积8像素
        //     enableAccumulation: true
        // );
    }
    
    public void ProcessMouseMove(int dx, int dy)
    {
        // 使用优化器处理移动
        var optimizedMovement = _optimizer.ProcessMovement(dx, dy);
        
        if (optimizedMovement.HasValue)
        {
            // 发送优化后的移动数据
            SendMouseMove(optimizedMovement.Value.dx, optimizedMovement.Value.dy);
        }
        // 否则忽略此次移动(已累积)
    }
    
    public void OnScreenSwitch()
    {
        // 屏幕切换时强制发送所有累积的移动
        var flushedMovement = _optimizer.FlushAccumulatedMovement();
        if (flushedMovement.HasValue)
        {
            SendMouseMove(flushedMovement.Value.dx, flushedMovement.Value.dy);
        }
        
        _optimizer.Reset();
    }
    
    private void SendMouseMove(int dx, int dy)
    {
        // 实际网络发送逻辑
        Debug.WriteLine($"Sending mouse move: ({dx},{dy})");
    }
    
    public void PrintStats()
    {
        var stats = _optimizer.Stats;
        Debug.WriteLine($"Optimization stats: " +
                       $"{stats.TotalEventsReceived} received, " +
                       $"{stats.TotalEventsSent} sent, " +
                       $"{stats.FilterRate:P0} filtered");
    }
}
相关推荐
燃尽了,可无1 小时前
C#基础编程核心知识点总结
开发语言·c#
我不是程序猿儿3 小时前
【C#】观察者模式 + UI 线程调度、委托讲解
观察者模式·ui·c#
专注VB编程开发20年4 小时前
c# .net支持 NativeAOT 或 Trimming 的库是什么原理
前端·javascript·c#·.net
钢铁男儿4 小时前
C# 简单工厂模式(简单工厂模式如何工作)
前端·c#·简单工厂模式
melonbo9 小时前
MHDD使用说明 - 硬盘检测
计算机外设
一枚小小程序员哈10 小时前
基于asp.net 的在线餐饮订餐系统的设计与实现/基于c#的网上订餐系统/餐厅管理系统
后端·c#·asp.net
好望角雾眠10 小时前
第三阶段数据库-7:sql中函数,运算符,常用关键字
数据库·笔记·sql·学习·sqlserver·c#
海绵宝宝汉堡包14 小时前
c# 项目 文件夹
开发语言·c#
曹牧17 小时前
C#:窗体间传值
c#