捕获和重放击键时间至关重要

时间:2012-02-02 15:29:01

标签: c# keyboard pinvoke

我正在尝试捕捉击键并在之后重播它们尽可能相等 (时间紧迫)


到目前为止我尝试了什么:

首先使用SetWindowsHookEx (使用WH_KEYBOARD_LL捕获密钥并记住扫描代码和时间戳(毫秒精度)

然后在捕获后将原始数据转换为预定义函数调用(C#)。 这些是使用SendInput使用已知扫描代码KeyUp结构中的KeyDown KEYEVENTF_SCANCODE和KEYBDINPUT方法> 但是,我对这些电话之间的等待部分表示担忧。目前我正在使用Thread.Sleep (单线程重播应用程序),但听说这不是非常精确。


我仍然在这里问你,你会想象当前的重播不是那么精确。 虽然每次都不一样!

我可以测量我的程序(或单个函数)的开销,并减去每次等待吗? 我应该尝试不同的方法吗?或者在我的想法中的其他地方是否存在问题?

(该程序不需要是可移植的,只能针对开发计算机进行调整)

1 个答案:

答案 0 :(得分:1)

不使用Thread.Sleep而是使用非常紧密的循环并且不断检查时差。你甚至可以让它变得有点聪明,对于任何不到一秒的时间,你只需要在紧密的循环中运行,并且任何超过一秒钟的时间你都会在一段时间内将它停留750毫秒,然后检查差异并继续这样做直到它不到一秒钟。

也许这样的东西,一个容纳你的工作项的课程:

public class workItem
{
    public int offset { get; set; }
    public string name { get; set; }
}

然后像这样使用它:

Queue<workItem> items = new Queue<workItem>();

items.Enqueue(new workItem() { offset = 200, name = "A" });
items.Enqueue(new workItem() { offset = 220, name = "B" });
items.Enqueue(new workItem() { offset = 240, name = "C" });
items.Enqueue(new workItem() { offset = 230, name = "D" });
items.Enqueue(new workItem() { offset = 250, name = "E" });
items.Enqueue(new workItem() { offset = 260, name = "F" });

DateTime start = DateTime.Now;
Debug.Print(DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.fff tt"));
while (items.Count > 0)
{
    var currItem = items.Dequeue();

    while (DateTime.Now < start.AddMilliseconds(currItem.offset))
    {

    }
    Debug.Print("{0}: {1}", DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.fff tt"), currItem.name);

}

它并不完美,因为在while循环中断和调试触发之间有时间,但它应该让你非常接近。一些评论也有可能有价值的链接(即使用WaitOne或并行任务)