捕获和重放时间关键的击键

发布于 2025-01-01 14:01:41 字数 1001 浏览 1 评论 0原文

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


到目前为止我尝试过的:

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

然后将原始数据转换为预定义的函数调用(C#) 捕获后。 这些是使用 SendInput 与已知的扫描代码KEYEVENTF_SCANCODE in KEYBDINPUT struct)

不过,我对这些调用之间的等待部分感到担忧。目前我正在使用 Thread.Sleep (单线程重放应用程序),但听说这不是很准确。


正如我仍然在这里问的那样,您会想象当前的重播并不像需要的那么准确。 每次都不同!

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

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

I'm trying to capture keystrokes and replay them afterwards as equal as possible (time critical).


What I tried so far:

First capture keys using SetWindowsHookEx (with WH_KEYBOARD_LL) and remember scan code and timestamp (milliseconds precision)

Then converting that raw data to predefined function calls (C#) after capture.
These are KeyUp and KeyDown methods implemented using SendInput with the known scan code (KEYEVENTF_SCANCODE in KEYBDINPUT struct)

I have concerns about the waiting part between these calls, though. Currently I'm using Thread.Sleep (single threaded replay application), but heard that would not be very precisely.


As I'm still asking here you'll imagine that the current replay is not as exact as needed. It differs the same each time though!

Could I measure the overhead of my program (or of the single functions) and substract that each wait?
Should I try a different approach? Or is there a problem somewhere else in my thoughts?

(the program doesn't need to be portable and can be tuned just for the dev computer)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

寒冷纷飞旳雪 2025-01-08 14:01:41

不使用 Thread.Sleep,而是使用非常紧密的循环,并不断检查时间差。你甚至可以让它变得有点聪明,对于任何低于一秒的事情,你只需在紧密循环中运行,对于任何超过一秒的事情,你都 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 或并行任务)

Instead of using Thread.Sleep use a very tight loop and just continually check the time difference. You could even make it somewhat smart that for anything under a second, you just run in the tight loop and anything over a second you thread.sleep for 750ms and then check the difference and keep doing that until it is under a second.

Maybe something like this, a class to hold your work items:

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

Then use it like this:

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);

}

It's not perfect because there is time between when the while loop breaks and the debug fires, but it should get you pretty close. Some of the comments also had links that might be valuable (i.e. using a WaitOne or the parallel tasks)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文