2016-11-08 2 views
1

Я делаю программу с глобальной мышью и клавиатурой. Программа будет записывать вход пользователя, когда они нажимают кнопку записи, и прекратит запись, как только они нажмут кнопку остановки. Я получаю временные интервалы каждого события, используя секундомер, поскольку это, по-видимому, самый точный метод.Выполнение мероприятий с очень быстрыми, точными и точными тарифами

Вот небольшой отрывок событий записи пользователя:

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 и время простоя секундомера, но это сильно всасывает процессор. Что бы вы сделали, чтобы точно воспроизвести события? Я трачу свое время на то, чтобы найти что-то настолько точное на рабочем столе?

+2

Процессы с низким уровнем клавиатуры уже включают в себя временную метку. Например, ['KBDLLHOOKSTRUCT'] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms644967 (v = vs.85) .aspx), который является одним из параметров в обратном вызове для крючка. Возможно, это лучший вариант, чем пытаться самостоятельно измерить метку времени. – vcsjones

+0

@vcsjones, Спасибо за это. Есть ли какие-либо подсказки о том, как правильно воспроизводить события? Должен ли я просто придерживаться «Таймера»? EDIT: Кроме того, с помощью 'KBDLLHOOKSTRUCT', до четырех событий иногда заканчивается тем же значением' time', что не кажется правильным, верно? – John

+0

Возможно, вам нужно будет найти ответ ниже: http://stackoverflow.com/questions/3729169/how-can-i-get-the-windows-system-time-with-millisecond-resolution – user6788933

ответ

1

Увеличьте разрешение таймера до 1 мс (это максимум). Затем используйте любой способ синхронизации (таймеры, сон, события, ...), чтобы получить точность 1 мс. 1000Гц должно быть достаточно для чего-либо, направленного на восприятие человека.

0

Взгляните на эту библиотеку: http://www.codeproject.com/Articles/28064/Global-Mouse-and-Keyboard-Library

Они просто используют Environment.TickCount и просто следить за тем, чтобы путь. Каждый раз, когда происходит событие мыши/клавиатуры, они сохраняют его в списке с указанием количества тиков. Затем, чтобы воспроизвести события, они просто просматривают список в фоновом потоке и спят для длины каждого события.

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; 
     } 
    } 
} 
+0

Известно ли это точно? Согласно http://stackoverflow.com/questions/1303667/how-accurate-is-thread-sleeptimespan, 'Thread.Sleep' не подходит для точности – John

+0

Я не могу сказать, насколько это точно. Я использовал эту библиотеку и магнитофон, и, похоже, он достаточно точен для стандартных действий. Если вам нужны гораздо более тесные тайминги, то, скорее всего, лучшим вариантом является комментарий относительно крючка просмотра журнала. –