Я пишу программу, которая реагирует на сочетание клавиш Alt+B пользователя. Программа продолжает печатать текущее время и Alt+B переключает цвет текст напечатан.
Я пытаюсь использовать PeekMessage, чтобы получить событие клавиатуры и создать ярлык Alt+B
работа. Однако это не работает, сочетание клавиш Alt+B не имеет никакого эффекта.
Почему это? Я так озадачен.
Ниже приведен мой код:
#include <stdio.h>
#include <windows.h>
void scta(WORD attributes)
{
SetConsoleTextAttribute (GetStdHandle(STD_OUTPUT_HANDLE), attributes);
}
void rcta(void)
{
scta(FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN);
}
void msgupd(BOOL *hotkey)
{
MSG msg = {0};
if (!PeekMessage(&msg,NULL,0,0,PM_REMOVE|PM_QS_INPUT))
return;
if (msg.message == WM_HOTKEY)
{
*hotkey=!*hotkey;
if (*hotkey)
scta(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
else
rcta();
}
}
int main()
{
RegisterHotKey(NULL,1,MOD_ALT|MOD_NOREPEAT,0x42);
BOOL hotkey=FALSE;
while(1)
{
msgupd(&hotkey);
SYSTEMTIME st;
GetSystemTime(&st);
printf ("\r%02d:%02d:%02d.%03d", (int)st.wHour, (int)st.wMinute, (int)st.wSecond, (int)st.wMilliseconds);
}
}
Функция msgupd проверяет сочетание клавиш и обновляет переменную HOTKEY, которая указывает, должен ли печатный текст быть цветным.
Переменная HOTKEY изначально равна FALSE, а Alt+B переключает ее. Однако, как упоминалось ранее, мне не удалось реализовать эту функцию. Я не знаю
почему PeekMessage не работает.
Функция scta() — это ярлык для SetConsoleTextAttribute,
изменение цвета печатаемого текста.
Функция rcta() сбрасывает эффект scta().
Я попробовал изменить PeekMessage с помощью GetMessage и получил от этого сообщение на клавиатуре. Но проблема в том, что GetMessage синхронен, поэтому мой код перестает печатать текст времени.
Я думаю, что можно переместить часть печати времени в
новую ветку, чтобы GetMessage было бы хорошо, но я думаю, что это гораздо сложнее, чем использовать PeekMessage.
ОБНОВЛЕНИЕ: магическое число 0x42 в RegisterHotKey — это буква «b», обозначающая Alt+B.
Документы, которые я прочитал:
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-peekmessagea
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerhotkey
Из документации PeekMessage. "PM_QS_POSTMESSAGE ((QS_POSTMESSAGE | QS_HOTKEY | QS_TIMER) << 16) Process all posted messages, including timers and hotkeys."
Если вы хотите углубиться в эти флаги. Learn.microsoft.com/en-us/windows/win32/api/winuser/…
@RetiredNinja Ааа... Спасибо! Я думаю, вот в чем проблема. Я думал, что HOTKEY является частью QS_INPUT... на самом деле это другое! Спасибо. :)
@n.m.couldbeanAI Спасибо! Я попробовал и моя проблема решена! Теперь он работает отлично. :D
@RetiredNinja Спасибо! После удаления |PM_QS_INPUT мой код работает отлично. Я прочитал документ и обнаружил, что HOTKEY отличается от других — я ошибочно принял его за одно из сообщений клавиатуры. :D Теперь моя проблема решена.
@Limina102: Да, документация в этом отношении немного вводит в заблуждение. Обратите внимание, что вы можете написать ответ на свой вопрос.





Удаление |PM_QS_INPUT решает проблему.
Я думал, что PM_QS_INPUT включает в себя события горячих клавиш, но на самом деле это так.
нет. В документе Microsoft PeekMessage PM_QS_POSTMESSAGE определен
как (QS_POSTMESSAGE | QS_HOTKEY | QS_TIMER) << 16, пока PM_QS_INPUT
как QS_INPUT. То есть QS_HOTKEY и QS_INPUT — это разные вещи. Документ GetQueueStatus дополнительно иллюстрирует это.
Таким образом, при назначении PM_QS_INPUT события QS_HOTKEY фильтруются «как указано». Вот почему моему PeekMessage не удалось получить событие горячей клавиши.
Попробуйте удалить
|PM_QS_INPUTи посмотрите, что произойдет.