这是一个快速而肮脏的解决方案:
让我们从几个变量开始:
List<Point> points = null;
Timer tt = null;
int index = 0;
现在有一个按钮开始重新编码;它初始化
List<Point>
收集位置并创建和启动
Timer
随着
lambda
在中进行重新编码的代码
Timer.Tick
事件:
private void btn_Record_Click(object sender, EventArgs e)
{
points = new List<Point>();
index = 0;
tt = new Timer()
{ Interval = 50, Enabled = true };
tt.Tick += (ss, ee) =>
{
if (!points.Any() || points.Last() != Control.MousePosition)
points.Add(Control.MousePosition);
};
}
下一步是停止录制的按钮:
private void btn_Stop_Click(object sender, EventArgs e)
{
if (tt!=null) tt.Stop();
}
最后是重播按钮;它使用索引在新的
计时器。打上钩
代码,但使用相同的计时器:
private void btn_Replay_Click(object sender, EventArgs e)
{
index = 0;
tt = new Timer() { Interval = 50, Enabled = true };
tt.Tick += (ss, ee) =>
{
if (index < points.Count)
{ System.Windows.Forms.Cursor.Position = points[index++]; }
else tt.Stop();
}
注意事项:
-
如问题所述,这将记录并回复Mmouse协调人。它会在固定的时间间隔内播放,因此播放看起来与原来的动作非常相似;事实上,很难区分,我添加了一个间隔较长的slowmo按钮来演示。。(但gif太大了)
-
该代码将在屏幕坐标中记录鼠标位置,并应在任何地方捕获鼠标位置,而不仅仅是在应用程序内部。查看VS如何激活代码loupe!
-
它不会记录任何其他鼠标事件,如向上、向下、单击、双击或滚轮。对于那些你需要一个全局鼠标钩子来捕获和一些外部调用来重播。
-
为了包含其他鼠标事件,您还需要一个不同的扩展数据结构;您还必须从计时器驱动的模型转向鼠标事件驱动的模型。
-
该示例使用按钮启动和停止。当然,这些按钮之间的移动也会包含在记录的位置列表中。相反,可以使用定时启动,它将在几秒钟后开始录制,并在几秒钟不活动后停止录制。。
有多种方法可以保存和加载点;最简单的方法是序列化为xml;使用
string path = @"..."
它可能看起来很简单:
private void btn_save_Click(object sender, EventArgs e)
{
if (points == null) points = new List<Point>();
XmlSerializer xs = new XmlSerializer((points).GetType());
using (TextReader tr = new StreamReader(path))
{
points = (List<Point>)xs.Deserialize(tr);
tr.Close();
}
}
private void btn_load_Click(object sender, EventArgs e)
{
XmlSerializer xs = new XmlSerializer((points).GetType());
using (TextWriter tw = new StreamWriter(path))
{
xs.Serialize(tw, points);
tw.Close();
}
}
其他方法是使用二进制格式化程序或自定义转换例程。Xml相对稳定。
以下是一个短片: