Захват и воспроизведение нажатий клавиш, критичных ко времени - PullRequest
1 голос
/ 02 февраля 2012

Я пытаюсь зафиксировать нажатия клавиш и затем воспроизвести их как можно более одинаково (критично по времени) .


Что я пробовал до сих пор:

Первые ключи захвата с использованием SetWindowsHookEx WH_KEYBOARD_LL) и запоминание кода и метки времени (с точностью до миллисекунд)

Затем преобразование этих необработанных данных в предварительно определенные вызовы функций (C #) после захвата. Это методы KeyUp и KeyDown, реализованные с использованием SendInput с известным кодом сканирования (KEYEVENTF_SCANCODE в KEYBDINPUT struct)

У меня есть опасения насчет ожидания между этими вызовами. В настоящее время я использую Thread.Sleep (однопоточное приложение воспроизведения) , но слышал, что это будет не очень точно.


Поскольку я все еще спрашиваю здесь, вы представите, что текущее воспроизведение не так точно, как необходимо. Хотя каждый раз он один и тот же!

Могу ли я измерить накладные расходы моей программы (или отдельных функций) и вычесть, что каждое ожидание? Должен ли я попробовать другой подход? Или в моих мыслях есть проблема?

(программа не должна быть переносимой и может быть настроена только для компьютера разработчика)

1 Ответ

1 голос
/ 02 февраля 2012

Вместо использования 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 или параллельных задач)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...