SendInput () не "отправляет" правильные смещенные символы? - PullRequest
7 голосов
/ 30 января 2010
void WriteChar(char c)
{
    INPUT input = {0};
    input.type = INPUT_KEYBOARD;
    input.ki.wVk= VkKeyScanEx(c, GetKeyboardLayout(0) ) ;   
    SendInput(1,&input, sizeof(INPUT));
}

VkKeyScanEx возвращает разные коды клавиш для «/» и «?» (Один и тот же ключ), однако, если вы попытаетесь использовать этот метод для написания сообщения, содержащего «?», Он будет писать только «/». Я не знаю, что происходит. То же самое происходит с ';' и ':'.

Я частично не понимаю коды клавиш и коды сканирования. Большинство символов имеют виртуальный код ключа, однако я не могу найти что-то похожее для вопросительных знаков. Они должны существовать, но их нет в списке?

Ответы [ 2 ]

9 голосов
/ 30 января 2010

Коды сканирования - это необработанные идентификаторы клавиш, возвращаемые с клавиатуры. Таким образом, клавиатура из 101 клавиши (в теории) будет иметь 101 уникальный код сканирования, который она может вернуть. (см. сноску 1 )

Виртуальные коды клавиш представляют собой отдельный набор кодов, которые представляют собой клавишу на идеализированной клавиатуре. Независимо от того, где на реальной клавиатуре находится клавиша TAB и какой код сканирования используется для нее, код виртуальной клавиши всегда равен VK_TAB. windows.h определяет коды VK_xxx для непечатаемых виртуальных ключей, для печатных - код виртуального ключа такой же, как значение ASCII.

Но коды виртуальных клавиш все еще являются кодами клавиш. «A» и «a» имеют одинаковый код виртуальной клавиши, поэтому, если вы хотите отправить «A», вы должны отправить VK_SHIFT вниз, затем «a» вниз, затем «a» вверх, затем VK_SHIFT вверх.

VkKeyScanEx() преобразует символ в ключ сканирования и сдвиг состояния См. Цитату ниже на этой странице http://msdn.microsoft.com/en-us/library/ms646332(VS.85).aspx

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

Так что вы не можете просто взять возврат из VkKeyScanEx (), вам нужно проверить, не помечен ли он на клавише Shift. и отправьте клавишу Shift как отдельное нажатие

SHORT vk = VkKeyScanEx(c, ...);
if (vk & 0x100) // check upper byte for shift flag
{
   // send a shift key down
}
if (vk & 0x200) // check for ctrl flag
{
   // send a ctrl key down
}
input.ki.wVk = vk & 0xFF;

// send keyup for each of the keydown

Вы также должны отправлять ключ для каждого нажатия.

Сноска:

1 Это только теоретически, на практике стандартные клавиатуры ПК эмулируют старую клавиатуру IBM, которую вы больше не можете получить, поэтому некоторые клавиши могут возвращать 2 разных кода сканирования на основе другой клавиши, в то время как в других случаях два ключа могут возвращать один и тот же код сканирования.

1 голос
/ 30 января 2010

Попробуйте сделать это так. Если вы сделаете это с помощью KEYEVENTF_UNICODE, платформой хоста должна быть версия Windows 2000 или XP.

INPUT input[ 2 ];

input[ 0 ].type = INPUT_KEYBOARD;
input[ 0 ].ki.wVk = 0;
input[ 0 ].ki.wScan = c;
input[ 0 ].ki.dwFlags = KEYEVENTF_UNICODE;
input[ 0 ].ki.time = 0;
input[ 0 ].ki.dwExtraInfo = GetMessageExtraInfo();

input[ 1 ].type = INPUT_KEYBOARD;
input[ 1 ].ki.wVk = 0;
input[ 1 ].ki.wScan = c;
input[ 1 ].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
input[ 1 ].ki.time = 0;
input[ 1 ].ki.dwExtraInfo = GetMessageExtraInfo();

SendInput( ( UINT )2, input, sizeof( *input ) );

Судя по тому, что вы неправильно заполнили структуру ввода и не инициализировали некоторые обязательные элементы, я бы предположил, что вы не видели документации для этого. См. SendInput , INPUT и KEYBDINPUT .

...