我正在编写一个具有全局鼠标和键盘钩子的程序。该程序将记录用户的输入,当他们按下录制按钮,将停止录制一旦他们按下停止按钮。我用秒表来计算每个事件的时间跨度,因为这似乎是最准确的方法。
下面是用户记录的事件的一小段:
01:45:20 - Time: 00:00:03.7028259 - Mousemove
01:45:20 - Time: 00:00:03.7190386 - Mouseleftdown
01:45:20 - Time: 00:00:03.7363274 - Mousemove
01:45:20 - Time: 00:00:03.7431332 - Mousemove
01:45:20 - Time: 00:00:03.7519057 - Mousemove
01:45:20 - Time: 00:00:03.7594302 - Mouseleftup
正如你所看到的,一些事件事件之间的间隔接近8毫秒(这似乎是我能在每个事件之间获得的最小时间)。
用户按下播放键,录音开始播放。首先,我研究了Timer
组件,因为它似乎非常适合这种情况。然而,这个组件相当不准确,所以我想在这里问一下。我考虑过创建一个带有秒表和while循环的新线程,该线程将比较事件TimeSpans和秒表的Elapsed time,但这将占用CPU很多。你们会怎么做才能准确地重现事件?我是在浪费时间在电脑上寻找如此精确的东西吗?
将计时器分辨率提高到1ms(这是最大值)。然后使用任何您喜欢的计时方法(计时器、睡眠、事件等)来获得1ms的精度。1000Hz对于任何针对人类感知的东西来说应该足够了。
看看这个库:http://www.codeproject.com/Articles/28064/Global-Mouse-and-Keyboard-Library
他们只是使用环境。TickCount,用这种方式记录它。每次鼠标/键盘事件发生时,它们将其保存到一个列表中,并带有tick计数。然后,为了回放事件,它们只需在后台线程中循环遍历列表,并休眠每个事件的长度。
void mouseHook_MouseMove(object sender, MouseEventArgs e)
{
events.Add(
new MacroEvent(
MacroEventType.MouseMove,
e,
Environment.TickCount - lastTimeRecorded
));
lastTimeRecorded = Environment.TickCount;
}
void mouseHook_MouseDown(object sender, MouseEventArgs e)
{
events.Add(
new MacroEvent(
MacroEventType.MouseDown,
e,
Environment.TickCount - lastTimeRecorded
));
lastTimeRecorded = Environment.TickCount;
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
foreach (MacroEvent macroEvent in events)
{
Thread.Sleep(macroEvent.TimeSinceLastEvent);
switch (macroEvent.MacroEventType)
{
case MacroEventType.MouseMove:
{
MouseEventArgs mouseArgs = (MouseEventArgs)macroEvent.EventArgs;
MouseSimulator.X = mouseArgs.X;
MouseSimulator.Y = mouseArgs.Y;
}
break;
case MacroEventType.MouseDown:
{
MouseEventArgs mouseArgs = (MouseEventArgs)macroEvent.EventArgs;
MouseSimulator.MouseDown(mouseArgs.Button);
}
break;
default:
break;
}
}
}