Windows API: почему PeekMessage не получил нужное мне событие клавиатуры?

Я пишу программу, которая реагирует на сочетание клавиш 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

Попробуйте удалить |PM_QS_INPUT и посмотрите, что произойдет.

n. m. could be an AI 29.05.2024 12:55

Из документации PeekMessage. "PM_QS_POSTMESSAGE ((QS_POSTMESSAGE | QS_HOTKEY | QS_TIMER) << 16) Process all posted messages, including timers and hotkeys."

Retired Ninja 29.05.2024 13:29

Если вы хотите углубиться в эти флаги. Learn.microsoft.com/en-us/windows/win32/api/winuser/…

Retired Ninja 29.05.2024 13:31

@RetiredNinja Ааа... Спасибо! Я думаю, вот в чем проблема. Я думал, что HOTKEY является частью QS_INPUT... на самом деле это другое! Спасибо. :)

Limina102 29.05.2024 13:37

@n.m.couldbeanAI Спасибо! Я попробовал и моя проблема решена! Теперь он работает отлично. :D

Limina102 29.05.2024 13:48

@RetiredNinja Спасибо! После удаления |PM_QS_INPUT мой код работает отлично. Я прочитал документ и обнаружил, что HOTKEY отличается от других — я ошибочно принял его за одно из сообщений клавиатуры. :D Теперь моя проблема решена.

Limina102 29.05.2024 13:49

@Limina102: Да, документация в этом отношении немного вводит в заблуждение. Обратите внимание, что вы можете написать ответ на свой вопрос.

Andreas Wenzel 29.05.2024 15:31
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
7
79
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Удаление |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 не удалось получить событие горячей клавиши.

Другие вопросы по теме