Это мой первый вопрос, который я разместил в stackoverflow. Я искал SendInput
для С++, чтобы моя программа «вводилась» в другую программу. Я решил начать с «ввода» пары слов с подчеркиванием в терминал. Я не обнаружил проблем с вводом заглавных и строчных букв, а также точки. Но после того, как вы дошли до символа подчеркивания, введя числовой идентификатор 95 для буквы подчеркивания, подчеркивание не отображалось и действовало так, как будто эта буква никогда не нажималась. Вот код, который я получил от cplusplus.com, на основе которого я его основал, он полностью функционален:
#include <iostream>
#include <windows.h>
using namespace std;
/* HWND = "Window Handle" */
HWND GameWindow = FindWindow(0, "Command Prompt");
/* This is a function to simplify usage of sending keys */
void GenerateKey(int vk, BOOL bExtended) {
KEYBDINPUT kb = {0};
INPUT Input = {0};
/* Generate a "key down" */
if (bExtended) { kb.dwFlags = KEYEVENTF_EXTENDEDKEY; }
kb.wVk = vk;
Input.type = INPUT_KEYBOARD;
Input.ki = kb;
SendInput(1, &Input, sizeof(Input));
/* Generate a "key up" */
ZeroMemory(&kb, sizeof(KEYBDINPUT));
ZeroMemory(&Input, sizeof(INPUT));
kb.dwFlags = KEYEVENTF_KEYUP;
if (bExtended) { kb.dwFlags |= KEYEVENTF_EXTENDEDKEY; }
kb.wVk = vk;
Input.type = INPUT_KEYBOARD;
Input.ki = kb;
SendInput(1, &Input, sizeof(Input));
return;
}
int main() {
/*
SetForegroundWindow will give the window focus for the
keyboard/mouse! In other words, you don't have to have
the game opened upfront in order to emulate key/mouse
presses, it's very helpful if it's a game that runs
in fullscreen mode, like StarCraft: Brood War does
*/
SetForegroundWindow(GameWindow);
GenerateKey(VK_CAPITAL, TRUE);
GenerateKey('I', FALSE);
GenerateKey(' ', FALSE);
GenerateKey(VK_CAPITAL, TRUE);
GenerateKey('A', FALSE);
GenerateKey('M', FALSE);
GenerateKey(' ', FALSE);
GenerateKey('C', FALSE);
GenerateKey('O', FALSE);
GenerateKey('O', FALSE);
GenerateKey('L', FALSE);
GenerateKey('E', FALSE);
GenerateKey('R', FALSE);
GenerateKey(' ', FALSE);
GenerateKey('T', FALSE);
GenerateKey('H', FALSE);
GenerateKey('A', FALSE);
GenerateKey('N', FALSE);
GenerateKey(' ', FALSE);
GenerateKey('Y', FALSE);
GenerateKey('O', FALSE);
GenerateKey('U', FALSE);
GenerateKey(' ', FALSE);
GenerateKey('W', FALSE);
GenerateKey('I', FALSE);
GenerateKey('L', FALSE);
GenerateKey('L', FALSE);
GenerateKey(' ', FALSE);
GenerateKey('E', FALSE);
GenerateKey('V', FALSE);
GenerateKey('E', FALSE);
GenerateKey('R', FALSE);
GenerateKey(' ', FALSE);
GenerateKey('B', FALSE);
GenerateKey('E', FALSE);
GenerateKey('n', FALSE);
GenerateKey(' ', FALSE);
GenerateKey(0x3A, FALSE); /* period key */
GenerateKey(0x0D, FALSE); /* enter key */
return 0;
}
И это код, который я сделал, который работал неправильно:
#include <iostream>
#include <fstream>
#include <windows.h>
using namespace std;
/* HWND = "Window Handle" */
HWND GameWindow = FindWindow(0, "Command Prompt");
/* This is a function to simplify usage of sending keys */
void GenerateKey(int vk, BOOL bExtended) {
KEYBDINPUT kb = {0};
INPUT Input = {0};
/* Generate a "key down" */
if (bExtended) { kb.dwFlags = KEYEVENTF_EXTENDEDKEY; }
kb.wVk = vk;
Input.type = INPUT_KEYBOARD;
Input.ki = kb;
SendInput(1, &Input, sizeof(Input));
/* Generate a "key up" */
ZeroMemory(&kb, sizeof(KEYBDINPUT));
ZeroMemory(&Input, sizeof(INPUT));
kb.dwFlags = KEYEVENTF_KEYUP;
if (bExtended) { kb.dwFlags |= KEYEVENTF_EXTENDEDKEY; }
kb.wVk = vk;
Input.type = INPUT_KEYBOARD;
Input.ki = kb;
SendInput(1, &Input, sizeof(Input));
return;
}
int main() {
/*
SetForegroundWindow will give the window focus for the
keyboard/mouse! In other words, you don't have to have
the game opened upfront in order to emulate key/mouse
presses, it's very helpful if it's a game that runs
in fullscreen mode, like StarCraft: Brood War does
*/
SetForegroundWindow(GameWindow);
GenerateKey(VK_CAPITAL, TRUE);
GenerateKey('N', FALSE);
GenerateKey(VK_CAPITAL, TRUE);
GenerateKey('I', FALSE);
GenerateKey('N', FALSE);
GenerateKey('J', FALSE);
GenerateKey('A', FALSE);
GenerateKey(0xBE, FALSE); // GenerateKey(0x3A, FALSE); did not work
GenerateKey(' ', FALSE);
GenerateKey(VK_CAPITAL, TRUE);
GenerateKey('H', FALSE);
GenerateKey(VK_CAPITAL, TRUE);
GenerateKey('I', FALSE);
GenerateKey('1', FALSE);
GenerateKey('2', FALSE);
GenerateKey('3', FALSE);
GenerateKey(95 , FALSE); // GenerateKey('_', FALSE); did not work either
GenerateKey('4', FALSE);
GenerateKey('5', FALSE);
GenerateKey('6', FALSE);
return 0;
}
Это выводит Ninja. Hi123456
вместо Ninja. Hi123_456
.
Другие вещи, достойные внимания:
1). Для периода ('.'), который был "введен", рабочий идентификатор был 0xBE
вместо 0x3A
.
2). Это было скомпилировано в Windows 10 с использованием Mingw.
Я надеюсь, что это было достаточно тщательно, спасибо заранее!
VK_SLEEP
, виртуальный код клавиши для спящего режима. Почему вы снова ожидаете, что он вызовет подчеркивание? Напомним, чтоSendInput
отправляет нажатия клавиш, а не символы. Какие символы генерируются этими нажатиями клавиш, зависит от раскладки клавиатуры принимающего потока. Нажатие клавиши сразу справа от Tab не всегда приводит кQ
. - person Igor Tandetnik   schedule 23.09.2018Shift
и нажимая клавишу дефиса (при американской раскладке клавиатуры). - person Sid S   schedule 23.09.2018Spy++
, чтобы увидеть, какие сообщения на самом деле отправляются в окно, когда вы используете клавиатуру. Он поставляется с Visual Studio. - person Sid S   schedule 23.09.2018