How to send keyboard events to all kind of applications in windows?
We have a simple C++ program which send/simulate return key events to an active window using keybd_event.
This works fine for all kind of windows apps. But we like to send the keyboard event to a 3rd party app like GTA (the game) — and this does not work. GTA does not receive the keyboard event.
Why does GTA not receive the keyboard event? Is there a way to get it working with keybd_event? Or is there any other solution to send events to all kind of apps (with a common windows or C++ standard library)?
2 Answers 2
keybd_event is the obsolete API call. Try to use moder SendInput API function
nInputs The number of structures in the pInputs array.
pInputs An array of INPUT structures. Each structure represents an event to be inserted into the keyboard or mouse input stream.
cbSize The size, in bytes, of an INPUT structure. If cbSize is not the size of an INPUT structure, the function fails.
This function is subject to UIPI. Applications are permitted to inject input only into applications that are at an equal or lesser integrity level.
The SendInput function inserts the events in the INPUT structures serially into the keyboard or mouse input stream. These events are not interspersed with other keyboard or mouse input events inserted either by the user (with the keyboard or mouse) or by calls to keybd_event , mouse_event , or other calls to SendInput .
This function does not reset the keyboard’s current state. Any keys that are already pressed when the function is called might interfere with the events that this function generates. To avoid this problem, check the keyboard’s state with the GetAsyncKeyState function and correct as necessary.
Because the touch keyboard uses the surrogate macros defined in winnls.h to send input to the system, a listener on the keyboard event hook must decode input originating from the touch keyboard. For more information, see Surrogates and Supplementary Characters.
An accessibility application can use SendInput to inject keystrokes corresponding to application launch shortcut keys that are handled by the shell. This functionality is not guaranteed to work for other types of applications.
Send Keys Класс
Определение
Предоставляет методы для отправки приложению сообщений о нажатиях клавиш. Provides methods for sending keystrokes to an application.
Примеры
В следующем примере кода показано, как использовать метод Send. The following code example demonstrates how to use the Send method. Чтобы выполнить пример, вставьте следующий код в форму с именем Form1, содержащую кнопку с именем Button1. To run the example, paste the following code in a form called Form1 containing a button called Button1. Убедитесь, что события щелчка связаны с методами обработки событий в этом примере. Ensure the click events are associated with their event-handling methods in this example. Свойству элемента управления «Кнопка» TabIndex должно быть присвоено значение 0. The button control’s TabIndex property should be set to 0. При выполнении примера дважды щелкните форму, чтобы активировать событие нажатия кнопки. When the example is running, double-click the form to trigger the button’s click event.
Комментарии
Используется SendKeys для отправки нажатий клавиш и сочетаний клавиш в активное приложение. Use SendKeys to send keystrokes and keystroke combinations to the active application. Для этого класса невозможно создание экземпляров. This class cannot be instantiated. Чтобы отправить нажатие клавиши в класс и сразу же продолжить работу с потоком программы, используйте Send . To send a keystroke to a class and immediately continue with the flow of your program, use Send. Для ожидания любых процессов, запущенных нажатием клавиши, используйте SendWait . To wait for any processes started by the keystroke, use SendWait.
Каждый ключ представлен одним или несколькими символами. Each key is represented by one or more characters. Чтобы указать одиночный символ клавиатуры, используйте сам символ. To specify a single keyboard character, use the character itself. Например, чтобы представить букву A, передайте в метод строку «A». For example, to represent the letter A, pass in the string «A» to the method. Чтобы представить более одного символа, добавьте каждый дополнительный символ в предыдущий. To represent more than one character, append each additional character to the one preceding it. Чтобы представить буквы A, B и C, укажите для параметра значение «ABC». To represent the letters A, B, and C, specify the parameter as «ABC».
Знак плюс (+), символ (^), знак процента (%), тильда (
) и круглые скобки () имеют специальное значение SendKeys . The plus sign (+), caret (^), percent sign (%), tilde (
), and parentheses () have special meanings to SendKeys. Чтобы указать один из этих символов, заключите его в фигурные скобки ( <> ). To specify one of these characters, enclose it within braces (<>). Например, чтобы указать знак «плюс», используйте «<+>«. For example, to specify the plus sign, use «<+>«. Чтобы указать символы фигурных скобок, используйте » < <>» и » <> >». To specify brace characters, use «<<>» and «<>>». Квадратные скобки ([]) не имеют особого смысла SendKeys , но их необходимо заключить в фигурные скобки. Brackets ([ ]) have no special meaning to SendKeys, but you must enclose them in braces. В других приложениях скобки имеют специальное значение, которое может быть значительным при выполнении динамического обмена данными (DDE). In other applications, brackets do have a special meaning that might be significant when dynamic data exchange (DDE) occurs.
Если приложение предназначено для международного использования с различными клавиатурами, применение метода Send может иметь непредсказуемые результаты и его следует избегать. If your application is intended for international use with a variety of keyboards, the use of Send could yield unpredictable results and should be avoided.
Чтобы указать символы, которые не отображаются при нажатии клавиши, например ENTER или TAB, а также ключи, представляющие действия, а не символы, используйте коды, приведенные в следующей таблице. To specify characters that aren’t displayed when you press a key, such as ENTER or TAB, and keys that represent actions rather than characters, use the codes in the following table.
Ключ Key | Код Code |
---|---|
BACKSPACE BACKSPACE | |
BREAK BREAK | РАЗБИЕНИ |
Caps Lock CAPS LOCK | |
DEL или DELETE DEL or DELETE | |
СТРЕЛКА ВНИЗ DOWN ARROW | КРЫВАЮЩЕЙ |
END END | КОНЦЕ |
ВВОД ENTER | |
ESC ESC | ESC |
HELP HELP | ПОЗВОЛЯЮТ |
HOME HOME | ДОМОМ |
INS или INSERT INS or INSERT | |
СТРЕЛКА ВЛЕВО LEFT ARROW | СЛЕВА |
NUM LOCK NUM LOCK | NumLock |
PAGE DOWN PAGE DOWN | Page Down |
PAGE UP PAGE UP | Page Up |
ПЕЧАТЬ ЭКРАНА PRINT SCREEN | <ПРТСК>(зарезервировано для будущего использования) |
СТРЕЛКА ВПРАВО RIGHT ARROW | СПРАВА |
ПРОКРУТИТЬ БЛОКИРОВКУ SCROLL LOCK | |
TAB TAB | ВКЛАДКЕ |
СТРЕЛКА ВВЕРХ UP ARROW | КРЫВАЮЩЕМСЯ |
F1 F1 | Справоч |
F2 F2 | F2 |
F3 F3 | F |
F4 F4 | Клавиш |
F5 F5 | Жмем |
F6 F6 | Нажат |
F7 F7 | 7 |
F8 F8 | 8 |
F9 F9 | F9 |
F10 F10 | F10 |
F11 F11 | F11 |
F12 F12 | F12 |
F13 F13 | |
F14 F14 | |
F15 F15 | |
F16 F16 | F16 |
Добавление клавиатуры Keypad add | ВКЛЮЧИТЬ |
Вычитание с клавиатуры Keypad subtract | ВЫЧЕСТЬ |
Умножение клавиатуры Keypad multiply | ПЕРЕМНОЖАЕМЫХ |
Разделительная клавиша Keypad divide | ДЕЛЕНИЕ |
Чтобы указать ключи в сочетании с любым сочетанием клавиш SHIFT, CTRL и ALT, перед кодом клавиши укажите один или несколько из следующих кодов. To specify keys combined with any combination of the SHIFT, CTRL, and ALT keys, precede the key code with one or more of the following codes.
Ключ Key | Код Code |
---|---|
МЕСТИ SHIFT | + |
КОМБИНАЦИ CTRL | ^ |
ALT ALT | % |
Чтобы указать, что сочетание клавиш SHIFT, CTRL и ALT должно удерживаться при нажатии нескольких других клавиш, заключите код этих клавиш в круглые скобки. To specify that any combination of SHIFT, CTRL, and ALT should be held down while several other keys are pressed, enclose the code for those keys in parentheses. Например, чтобы указать, чтобы при нажатии клавиш «E» и «C» использовались клавиши SHIFT, используйте «+ (EC)». For example, to specify to hold down SHIFT while E and C are pressed, use «+(EC)». Чтобы указать, что при нажатии клавиши «E», а затем C без СДВИГа, следует использовать «+ EC». To specify to hold down SHIFT while E is pressed, followed by C without SHIFT, use «+EC».
Чтобы указать повторяющиеся ключи, используйте форму <номер ключа>. To specify repeating keys, use the form
Поскольку нет управляемого метода для активации другого приложения, можно либо использовать этот класс в текущем приложении, либо использовать собственные методы Windows, такие как FindWindow и SetForegroundWindow , чтобы принудительно сосредоточиться на других приложениях. Because there is no managed method to activate another application, you can either use this class within the current application or use native Windows methods, such as FindWindow and SetForegroundWindow , to force focus on other applications.
Класс SendKeys был обновлен в .NET Framework 3.0, что позволило использовать его в приложениях, работающих в Windows Vista. The SendKeys class has been updated for the .NET Framework 3.0 to enable its use in applications that run on Windows Vista. Усиленная система безопасности Windows Vista (известная как контроль учетных записей или UAC) не позволяет предыдущей реализации работать должным образом. The enhanced security of Windows Vista (known as User Account Control or UAC) prevents the previous implementation from working as expected.
Класс SendKeys подвержен проблемам со временем, которые пришлось решать некоторым разработчикам. The SendKeys class is susceptible to timing issues, which some developers have had to work around. Обновленная реализация по-прежнему подвержена этим проблемам, но она работает немного быстрее, поэтому существующие решения может потребоваться переработать. The updated implementation is still susceptible to timing issues, but is slightly faster and may require changes to the workarounds. Класс SendKeys сначала пытается использовать предыдущую реализацию, и если это не удается, использует новую реализацию. The SendKeys class tries to use the previous implementation first, and if that fails, uses the new implementation. В результате класс SendKeys может работать по-разному в разных операционных системах. As a result, the SendKeys class may behave differently on different operating systems. Кроме того, при использовании новой реализации класса SendKeys метод SendWait не будет дожидаться обработки сообщений, если они отправляются другому процессу. Additionally, when the SendKeys class uses the new implementation, the SendWait method will not wait for messages to be processed when they are sent to another process.
Если необходимо обеспечить согласованное поведение приложения независимо от операционной системы, можно заставить класс SendKeys использовать новую реализацию, добавив указанный ниже параметр приложения в файл app.config. If your application relies on consistent behavior regardless of the operating system, you can force the SendKeys class to use the new implementation by adding the following application setting to your app.config file.
Для принудительного использования классом SendKeys предыдущей реализации задайте значение «JournalHook» . To force the SendKeys class to use the previous implementation, use the value «JournalHook» instead.
Методы
Определяет, равен ли указанный объект текущему объекту. Determines whether the specified object is equal to the current object.
(Унаследовано от Object)
Обрабатывает все сообщения Windows, находящиеся в настоящий момент в очереди сообщений. Processes all the Windows messages currently in the message queue.
Служит хэш-функцией по умолчанию. Serves as the default hash function.
(Унаследовано от Object)
Возвращает объект Type для текущего экземпляра. Gets the Type of the current instance.
(Унаследовано от Object)
Создает неполную копию текущего объекта Object. Creates a shallow copy of the current Object.
(Унаследовано от Object)
Посылает сообщения о нажатии клавиш активному приложению. Sends keystrokes to the active application.
Отправляет данные об указанных клавишах активному приложению и ожидает окончания обработки сообщений. Sends the given keys to the active application, and then waits for the messages to be processed.
Возвращает строку, представляющую текущий объект. Returns a string that represents the current object.
KeyboardEvent.key
Ключ события KeyboardEvent key доступен только для чтения, возвращает значение клавиши, нажатой пользователем, принимая во внимание состояние клавиш-модификаторов, таких как Shift , а также локаль и раскладку клавиатуры. Его значение определяется следующим образом:
Key values
See a full list of key values.
- If the pressed key has a printed representation, the returned value is a non-empty Unicode character string containing the printable representation of the key.
- If the pressed key is a control or special character, the returned value is one of the pre-defined key values.
- If the KeyboardEvent represents the press of a dead key, the key value must be » Dead «.
- Some specialty keyboard keys (such as the extended keys for controlling media on multimedia keyboards) don’t generate key codes on Windows; instead, they trigger WM_APPCOMMAND events. These events get mapped to DOM keyboard events, and are listed among the «Virtual key codes» for Windows, even though they aren’t actually key codes.
- If the key cannot be identified, the returned value is «Unidentified» .
KeyboardEvent sequence
Every KeyboardEvent is fired in a pre-determined sequence. For a given key press, the sequence of KeyboardEvent s fired is as follows assuming that Event.preventDefault is not called:
- A keydown (en-US) event is first fired. If the key is held down further and the key produces a character key, then the event continues to be emitted in a platform implementation dependent interval and the KeyboardEvent.repeat (en-US) read only property is set to true .
- If the key produces a character key that would result in a character being inserted into possibly an ,
(en-US) or an element with HTMLElement.contentEditable set to true, the beforeinput and input (en-US) event types are fired in that order. Note that some other implementations may fire keypress (en-US) event if supported. The events will be fired repeatedly while the key is held down.
In sequence 1 & 3, the KeyboardEvent.key attribute is defined and is set appropriately to a value according to the rules defined ealier.
KeyboardEvent sequence example
Consider the event sequence generated when we interact with the Shift and the 2 key using a U.S keyboard layout as compared to when we do so using a UK keyboard layout.
Try experimenting using the following two test cases:
- Press and hold the Shift key, then press 2 and release it. Next, release the Shift key.
- Press and hold the Shift key, then press and hold 2 . Release the Shift key. Finally, release 2 .
JavaScript
Result
Note: On browsers that don’t fully implement the InputEvent interface which is used for the beforeinput and input (en-US) events, you may get incorrect output on those lines of the log output.
Case 1
When the shift key is pressed, a keydown (en-US) event is first fired, and the key property value is set to the string «Shift» . As we keep holding this key, the keydown (en-US) event does not continue to fire repeatedly because it does not produce a character key.
When key 2 is pressed, another keydown (en-US) event is fired for this new key press, and the key property value for the event is set to the string «@» for the U.S keyboard type and «»» for the UK keyboard type, because of the active modifier shift key. The beforeinput and input (en-US) events are fired next because a character key has been produced.
As we release the key 2 , a keyup (en-US) event is fired and the key property will maintain the string values «@» and «»» for the different keyboard layouts respectively.
As we finally release the shift key, another keyup (en-US) event is fired for it, and the key attribute value remains «Shift» .
Case 2
When the shift key is pressed, a keydown (en-US) event is first fired, and the key property value is set to be the string «Shift» . As we keep holding this key, the keydown event does not continue to fire repeatedly because it produced no character key.
When key 2 is pressed, another keydown (en-US) event is fired for this new key press, and the key property value for the event is set to be the string «@» for the U.S keyboard type and «»» for the UK keyboard type, because of the active modifier shift key. The beforeinput and input (en-US) events are fired next because a character key has been produced. As we keep holding the key, the keydown (en-US) event continues to fire repeatedly and the KeyboardEvent.repeat (en-US) property is set to true . The beforeinput and input (en-US) events are fired repeatedly as well.
As we release the shift key, a keyup (en-US) event is fired for it, and the key attribute value remains «Shift» . At this point, notice that the key property value for the repeating keydown event of the key 2 key press is now «2» because the modifier shift key is no longer active. The same goes for the InputEvent.data (en-US) property of the beforeinput and input (en-US) events.
As we finally release the key 2 , a keyup (en-US) event is fired but the key property will be set to the string value «2» for both keyboard layouts because the modifier shift key is no longer active.