以非常快速、精确和准确的速率执行事件
Executing events at very fast, precise, and accurate rates
我正在制作一个带有全局鼠标和键盘挂钩的程序。该程序将在用户按下录制按钮时记录用户的输入,并在用户按下停止按钮后停止录制。我使用秒表获取每个事件的时间跨度,因为这似乎是最准确的方法。
以下是用户录制的一小段事件:
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 和秒表的运行时间,但这会占用 CPU 很多。你们会怎么做才能准确重播这些事件?我是在浪费时间在桌面上寻找如此准确的东西吗?
看看这个图书馆:http://www.codeproject.com/Articles/28064/Global-Mouse-and-Keyboard-Library
他们只是使用 Environment.TickCount 并以这种方式跟踪它。每次发生 mouse/keyboard 事件时,他们都会将其保存到一个列表中,并附上滴答计数。然后,为了回放事件,他们只需在后台线程中循环遍历列表并在每个事件的长度内休眠。
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;
}
}
}
将计时器分辨率提高到 1 毫秒(最大值)。然后使用您喜欢的任何计时方法(计时器、睡眠、事件……)以获得 1 毫秒的精度。 1000Hz 应该足以满足任何针对人类感知的需求。
我正在制作一个带有全局鼠标和键盘挂钩的程序。该程序将在用户按下录制按钮时记录用户的输入,并在用户按下停止按钮后停止录制。我使用秒表获取每个事件的时间跨度,因为这似乎是最准确的方法。
以下是用户录制的一小段事件:
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 和秒表的运行时间,但这会占用 CPU 很多。你们会怎么做才能准确重播这些事件?我是在浪费时间在桌面上寻找如此准确的东西吗?
看看这个图书馆:http://www.codeproject.com/Articles/28064/Global-Mouse-and-Keyboard-Library
他们只是使用 Environment.TickCount 并以这种方式跟踪它。每次发生 mouse/keyboard 事件时,他们都会将其保存到一个列表中,并附上滴答计数。然后,为了回放事件,他们只需在后台线程中循环遍历列表并在每个事件的长度内休眠。
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;
}
}
}
将计时器分辨率提高到 1 毫秒(最大值)。然后使用您喜欢的任何计时方法(计时器、睡眠、事件……)以获得 1 毫秒的精度。 1000Hz 应该足以满足任何针对人类感知的需求。