C# 用C求鼠标的速度#
如何在鼠标释放的确切时刻找到鼠标的瞬时垂直速度?我让用户在自定义控件上拖动,当他们释放时,我需要知道这些信息,以便我可以使用速度的垂直分量继续拖动对象 例如,如果它们以一定角度拖动,则使用trig来确定垂直速度,然后使用它 我不能只计算时间的距离,因为鼠标可以以不规则的速度移动,这根本不能代表正确的速度 我在想我可以使用MouseMove的触发器之间可能有一个特定的间隔,但我不确定 如何在鼠标释放的确切时刻找到鼠标的瞬时垂直速度C# 用C求鼠标的速度#,c#,winforms,winapi,mouseevent,C#,Winforms,Winapi,Mouseevent,如何在鼠标释放的确切时刻找到鼠标的瞬时垂直速度?我让用户在自定义控件上拖动,当他们释放时,我需要知道这些信息,以便我可以使用速度的垂直分量继续拖动对象 例如,如果它们以一定角度拖动,则使用trig来确定垂直速度,然后使用它 我不能只计算时间的距离,因为鼠标可以以不规则的速度移动,这根本不能代表正确的速度 我在想我可以使用MouseMove的触发器之间可能有一个特定的间隔,但我不确定 如何在鼠标释放的确切时刻找到鼠标的瞬时垂直速度 你不能。正如芝诺几个世纪前明确指出的那样,速度只有在一段时间内才有
你不能。正如芝诺几个世纪前明确指出的那样,速度只有在一段时间内才有意义。如果必须这样做,我可能会使用加权移动平均值,因此(例如)我计算了最后5条鼠标移动消息的距离/时间,但它们的重要性随着时间的推移而“衰减”。例如,我可以将最近的值乘以1,下一个值乘以.8,下一个值乘以.6,依此类推。这样,如果(例如)他们恰好在松开按钮时减慢(或加速)运动,你仍然可以得到他们在此之前所做的合理近似值。你要求计算距离-时间曲线末端的速度,这在微积分中是不可能的
我建议你最好在最适合你的曲线末端做一个短的时间段,然后计算出几乎相同的速度我要做的是不断地对鼠标移动进行采样,并跟踪(比如)最后10个位置。然后,当鼠标按钮被释放时,您将拥有一组测量值,这些测量值允许您在鼠标被释放时估计鼠标速度 我写了一个快速的winform应用程序来实现这个想法。这将计算 鼠标每次移动的速度。您需要调整队列长度
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
namespace MouseVelocity
{
public partial class Form1 : Form
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
Queue timePoints;
public Form1()
{
sw.Start();
timePoints = new Queue(100);
InitializeComponent();
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
addPoint(e);
}
private void addPoint(MouseEventArgs e)
{
timePoints.Enqueue(new TimePoint(new Point(e.X, e.Y), sw.ElapsedMilliseconds));
if (timePoints.Count == 40) timePoints.Dequeue();
object[] array = timePoints.ToArray();
TimePoint tip = (TimePoint)array[array.Length - 1];
TimePoint end = (TimePoint)array[0];
long deltaX = tip.point.X - end.point.X;
long deltaY = tip.point.Y - end.point.Y;
long distance = deltaX * deltaX + deltaY * deltaY;
long deltaT = tip.time - end.time;
double velocity_modulo = Math.Sqrt(distance) / deltaT;
double velocity_X = deltaX / (double)deltaT;
double velocity_Y = deltaY / (double)deltaT;
label1.Text = string.Format("|V| = {0}; Vx = {1}; Vy = {2}", velocity_modulo, velocity_X, velocity_Y);
}
}
public class TimePoint
{
public Point point;
public long time;
public TimePoint(Point pt, long ms)
{
point = pt;
time = ms;
}
}
}
考虑pinvoking GetMouseMovePointsEx()。它可以为您提供高达64点的移动历史记录。每个点都有一个时间戳,允许您精确计算速度。由于时间戳不受在消息队列中缓冲鼠标移动消息所产生的任何延迟的影响,因此它可以使您获得更高的准确性。你可以用鼠标原生单位而不是像素来获取点。访问pinvoke.net了解声明。我想Zeno是在我们讨论数学之前发表评论的。顺便说一句,在这种情况下,你有一个离散的时间步长。@stefan:你到底在说什么?@Jerry Coffin仅仅因为你需要时间框架并不意味着你不能说出按钮松开时的准确速度。它永远不会在时间=0时发生,也不会在time@stefan:对不起,没有。速度是以每单位时间的距离为单位给出的。将时间减少到零时,距离也始终为零。这意味着0除以0,这是未定义的。最接近于这一点的数学是微积分,它可以让你在接近瞬间时计算速度,但永远不会让你真正达到瞬间。微积分不会让你去有不连续的地方,这正是在这种情况下发生的。@stefan:你释放它的时间并不重要。关键是,你只能计算之前一段时间的速度,而不仅仅是在它发布的那一刻。我尝试过这样做,但遇到了一些问题。见我的问题。