SendKeys на C++
Перенос C++ и доработка функции SendKeys C# / VB
• Скачать исходники и демо - 29 Кб
Введение
Однажды понадобилось отправлять клавиши другому приложению, чтобы автоматизировать задачу из программы C++, но после изучения не было найдено простого способа делать это в C++, и была найдена лишь ссылка на SendKeys VB или C#. Однако один из результатов поиска выдал sndkeys32.pas, являющийся версией кода SendKeys() на Delphi, написанной Кеном Хендерсоном в 1995 году.
Поскольку требовалась такая же функциональность на C++, было решено перенести и доработать код, чтобы он удовлетворял потребности. Остальная статья объяснит принцип отправки клавиш в Win32 и покажет, как использовать код, чтобы отправлять клавиши всего двумя строками кода.
Принцип отправки клавиш в Win32
Основой функциональности отправки клавиш в CSendKeys является использование функции Win32 API keybd_event().
keybd_event() производит нажатие клавиши, однако прерывание драйвера клавиатуры обрабатывает вызовы этой функции, а значит, можно отправлять почти любое сочетание клавиш с незначительными ограничениями.
Вкратце, это позволяет отправлять виртуальную клавишу, определенную в winuser.h как VK_XXX, и флаг, обозначающий KeyDown(клавиша нажата), KeyUp(клавиша отпущена) или состояние, сообщающее, является ли VKey расширенной клавишей.
Нормальные символы переводятся в виртуальные клавиши посредством VkKeyScan(), принимающей CHAR и возвращающей WORD, обозначающий виртуальную клавишу.
При отправке клавиши она будет нажата до тех пор, пока не будет отправлена снова с флагом KEYEVENTF_KEYUP.
Ниже приведен маленький фрагмент кода, отправляющий сочетание клавиш ALT-TAB:
// нажать "Alt-Tab"
keybd_event(VK_MENU, 0, 0, 0);
keybd_event(VK_TAB, 0, 0, 0);
::Sleep(1000);
// отпустить "Alt-Tab"
keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
keybd_event(VK_TAB, 0, KEYEVENTF_KEYUP, 0);
Как видно, для отправки этого простого сочетания клавиш понадобилось 4 строки кода. Здесь вступает в действие CSendKeys, чтобы упростить данную задачу.
Как использовать код
Вкратце, код можно использовать следующим образом:
#include "SendKeys.h"
.
.
.
CSendKeys sk;
// Отправить "Hello world!"
sk.SendKeys("Hello world!");
.
.
.
.
.
.
// Запустить блокнот
sk.SendKeys("{DELAY=50}@rnotepad{ENTER}");
CSendKeys отчасти предназначен для сохранения определенной совместимости с SendKeys из C#, при этом добавляя дополнительную функциональность. Поэтому если вы раньше использовали SendKeys.Send() из C# или из VB, то использовать CSendKeys станет легче.
Каждую клавишу представляет один или несколько символов. Чтобы указать один клавиатурный символ, используйте сам символ. Например, чтобы представить букву 'a', передайте строку "a" методу. Чтобы представить строку символов, передайте их по порядку, как "hello".
Если вы хотите отправить клавиши-модификаторы, такие как клавиши SHIFT, ALT, CONTROL или WINKEY, в дополнение к нормальным клавишам, используйте любой из символов, определенных в таблице 3.
Например, если вы хотите отправить "A", то обычно нажимаете Shift+A, что равноценно отправке таких нажатий клавиш: "+a", аналогично для отправки "~" нажимается Shift+`, что равноценно нажатиям клавиш "+`" или просто "{TILDE}" (таблица 1.b).
Все символы в таблице 3 зарезервированы и имеют специальное значение в дополнение к левым или правым круглым или квадратным скобкам.
Круглые скобки используются для связывания заданного модификатора или модификаторов с группой символов. Например, отправка "HELLO" описывается как "+(hello)", что сообщает CSendKeys нажать клавишу SHIFT при отправке следующей группы клавиш. Тогда как квадратные скобки используются для закрытия любых клавиш, представленных в таблице 1 и 2.
Отправленные клавиши не отправляются конкретному приложению, вместо этого они просто нажимаются, и любое приложение, имеющее ввод с клавиатуры, примет клавиши.
Чтобы отправить клавиши конкретному окну/приложению, используйте любой из методов:
// 1. активировать приложение с помощью его описателя
sk.AppActivate(hWnd);
// 2. активировать приложение, указав заголовок его окна
sk.AppActivate("Title");
/// 3. активировать приложение, указав заголовок его окна и/или класс его окна
sk.AppActivate(NULL, "TheClass"); // NULL значит, что этот критерий не нужен
// 4. посредством метода SendKeys
sk.SendKeys("{appactivate Notepad}hello");
Следующая таблица – слегка измененный вариант справки MSDN/SendKeys:
Клавиша |
Код |
BACKSPACE |
{BACKSPACE}, {BS} или {BKSP} |
BREAK |
{BREAK} |
CAPS LOCK |
{CAPSLOCK} |
DEL или DELETE |
{DELETE} или {DEL} |
DOWN ARROW |
{DOWN} |
END |
{END} |
ENTER |
{ENTER} или ~ |
ESC |
{ESC} |
HELP |
{HELP} |
HOME |
{HOME} |
INS or INSERT |
{INS} |
LEFT ARROW |
{LEFT} |
NUM LOCK |
{NUMLOCK} |
PAGE DOWN |
{PGDN} |
PAGE UP |
{PGUP} |
PRINT SCREEN |
{PRTSC} (зарезервировано впрок) |
RIGHT ARROW |
{RIGHT} |
SCROLL LOCK |
{SCROLL} |
TAB |
{TAB} |
UP ARROW |
{UP} |
F1 |
{F1} |
F2 |
{F2} |
F3 |
{F3} |
F4 |
{F4} |
F5 |
{F5} |
F6 |
{F6} |
F7 |
{F7} |
F8 |
{F8} |
F9 |
{F9} |
F10 |
{F10} |
F11 |
{F11} |
F12 |
{F12} |
F13 |
{F13} |
F14 |
{F14} |
F15 |
{F15} |
F16 |
{F16} |
Сложение на дополнительной клавиатуре |
{ADD} |
Вычитание на дополнительной клавиатуре |
{SUBTRACT} |
Умножение на дополнительной клавиатуре |
{MULTIPLY} |
Деление на дополнительной клавиатуре |
{DIVIDE} |
(таблица 1.a)
Ниже приведены дополнения:
Клавиша |
Код |
+ |
{PLUS} |
@ |
{AT} |
APPS |
{APPS} |
^ |
{CARET} |
~ |
{TILDE} |
{ } |
{LEFTBRACE} {RIGHTBRACE} |
( ) |
{LEFTPAREN} {RIGHTPAREN} |
Левый/правый WINKEY |
{LWIN} {RWIN} |
WINKEY |
{WIN} эквивалентно {LWIN} |
(таблица 1.b)
Кроме того, было добавлено несколько специальных клавиш, действующих как команды:
Синтаксис команды |
Действие |
{VKEY X} |
Отправляет VKEYзначения X. Очень полезна, если вы не хотите перекомпилировать CSendKeysи добавлять новый Vkeyв жестко закодированную таблицу специальных клавиш. Например, {VKEY 13} эквивалентно VK_RETURN. |
{BEEP X Y}} |
Подает звуковой сигнал с частотой Xи длительностью Y миллисекунд. |
{DELAY X} |
Задерживает отправку следующей клавиши на Xмиллисекунд. После задержки следующей клавиши затем последующие клавиши не будут задерживаться, если нет значения задержки по умолчанию (смотрите DELAY=X). Пример: {DELAY 1000} <-- задерживает последующее нажатие клавиши на 1 секунду. |
{DELAY=X} |
Устанавливает значение задержки по умолчанию на Xмиллисекунд. При этом каждая клавиша будет задерживаться на Xмс. Если значение уже установлено, и вы задаете {DELAYY}, то следующая клавиша задержится на Yмс, но последующие клавиши будут задерживаться на Xмс. Пример: {DELAY=1000} <-- все последующие клавиши будут задержаны на 1 секунду. |
{APPACTIVATE WindowTitle} |
Активирует приложение с помощью его WindowTitle. Очень полезно для отправки разных клавиш разным приложениям. |
(таблица 2)
Клавиша |
Код |
WINKEY |
@ |
SHIFT |
+ |
CTRL |
^ |
ALT |
% |
(таблица 3)
Ниже дано несколько примеров:
Нажатия клавиш |
Описание |
{DELAY=50}@rnotepad~hello world%ha |
|
{delay=100}{appactivate Calculator}{ESC}5*7~{beep 1000 500}^c{appactivate Notepad}^a{DEL}Result of 5*7 is: ^v |
При условии, что "Calc.exe" и "Notepad.exe" работают:
|
{DELAY=500}{NUMLOCK}{CAPSLOCK}{SCROLL}{SCROLL}{CAPSLOCK}{NUMLOCK} |
|
{DELAY=500}% {DOWN 5} |
|
(таблица 4)
Дополнительные примеры смотрите в сопутствующем примере кода.