这个封装类可以独立于具体的网络传输逻辑,为任何需要减少鼠标移动数据量的应用提供灵敏度和数据量优化。
核心优化功能
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");
}
}