Я пытаюсь синтезировать нажатия клавиш с помощью PostMessage()
, и мне нужно сгенерировать соответствующие lParam
.
Я знаком со структурой KeyStrokeMessage.
Вот код:
///-------------------------------------------------------------------------------------------
/// KeystrokeMessage/KeyLParam struct
///-------------------------------------------------------------------------------------------
typedef struct KeystrokeMessage
{
unsigned RepeatCount : 16;
unsigned ScanCode : 8;
unsigned ExtendedFlag : 1;
unsigned Reserved : 4;
unsigned ContextCode : 1;
unsigned PreviousKeyState : 1;
unsigned TransitionState : 1;
} KeyLParam;
///-------------------------------------------------------------------------------------------
/// GetKeyMessageLPARAM:
/// Creates an LPARAM for key messages.
///-------------------------------------------------------------------------------------------
LPARAM GetKeyMessageLPARAM(unsigned aVKey, bool aIsDown, bool aIsSystem)
{
KeyLParam lp;
UINT sc = MapVirtualKeyA(aVKey, MAPVK_VK_TO_VSC_EX);
lp.RepeatCount = 1;
lp.ScanCode = LOBYTE(sc);
lp.ExtendedFlag = (HIBYTE(sc) == 0xE0 || HIBYTE(sc) == 0xE1) ? 1 : 0;
lp.Reserved = 0;
lp.ContextCode = aIsSystem ? 1 : 0;
lp.PreviousKeyState = aIsDown ? 0 : 1;
lp.TransitionState = aIsDown ? 0 : 1;
return *(LPARAM*)&lp;
}
Я также перехватывал подлинные нажатия клавиш, чтобы понять, что я делаю не так.
В частности, я пытаюсь синтезировать нажатие клавиши «стрелка вверх», то есть VK_UP
.
В настоящем сообщении для «стрелки вверх» wParam
установлен на VK_UP
, а lParam
имеет скан-код 0x48
с установленным расширенным флагом.
Подлинное нажатие клавиши для справки:
Сканкод должен быть 0xE048
(с расширенным флажком).
Однако MapVirtualKey()
возвращает 72 (0x48
) и поэтому не устанавливает ExtendedFlag
.
В документации на MSDN указано, что он вернет расширенный флаг.
Я пробовал MapVirtualKey()
и MapVirtualKeyEx()
.
В версиях Ex
я пробовал как фактическую раскладку клавиатуры, так и оставлял ее равной 0.
Я использую правильный тип карты MAPVK_VK_TO_VSC_EX
, но я также попробовал MAPVK_VK_TO_VSC
посмотреть, отличается ли результат.
Я даже попробовал пойти обратным путем, начав с фактического скан-кода и преобразуя его в виртуальный ключ, а затем обратно в скан-код.
Я получаю правильный VK_UP
, но повторная попытка получить скан-код возвращает неверный ключ.
Независимо от ввода, я никогда не получаю возвращенный расширенный флаг, даже если он должен быть. Я также сделал перекрестную ссылку на свою раскладку клавиатуры через https://kbdlayout.info, и это должно быть 0xE048
.
Как мне получить расширенный флаг от MapVirtualKeyA()
?
Приложение, которому я отправляю синтезированные входные данные, прекрасно справляется с этим, как и ожидалось. Я пытаюсь синтезировать входные данные только для этого приложения, а не глобально. Это один из вариантов использования, где подход полностью оправдан.
Воспроизведено, и это может быть проблема API. Возможно, вам придется внести изменения в возвращаемое значение на основе флага расширенного ключа .
Отвечаю на свой вопрос, если кто-то еще наткнется на такое поведение:
Возвращаемое значение технически правильное, поскольку MapVirtualKey
по умолчанию соответствует нерасширенной версии, а VK_UP
используется как клавишей «стрелка вверх» (0xE048
), так и цифровой клавиатурой 8 (0x48
). Некоторые другие клавиши также используют один и тот же виртуальный код ключа, например VK_RETURN
.
Для справки: VK_NUMPAD8
существует и может использоваться в некоторых других макетах, но не в этом случае.