wm keydown коды клавиш
КАК взаимодействуют окно и клавиатура?
Остаётся только узнать эти коды. Их можно посмотреть в справочнике по программированию или самому написать программу, которая выводит на экран коды клавиш и их сочетаний. Чем мы сейчас и займёмся.
Создайте новый пустой проект Win32, который назовём: «MyKey». В папке проекта создадим новый текстовый файл и сохраним его под именем MyKey.cpp. В нём будет исходный текст программы. Добавим его в проект с помощью команды меню: Project->Add to project->Files (Project->Add Existing Item для 7-й версии). Теперь наберите в этот файл следующий текст:
//Отображение кодов нажатых клавиш
//Создаём прототип функции окна
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
char szProgName[]=»Progname»; //имя программы
char szText[]=»»;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
<
HWND hWnd; //идентификатор окна
MSG lpMsg; //идентификатор сообщения
WNDCLASS w; //создаём экземпляр структуры WNDCLASS
//Выводим окно из памяти на экран
ShowWindow(hWnd, nCmdShow);
//Обновим содержимое окна
UpdateWindow(hWnd);
//Цикл обработки сообщений
while(GetMessage(&lpMsg, NULL, 0, 0)) < //Получаем сообщение из очереди
TranslateMessage(&lpMsg); //Преобразует сообщения клавиш в символы
DispatchMessage(&lpMsg); //Передаёт сообщение соответствующей функции окна
>
return(lpMsg.wParam);
>
//Функция окна
LRESULT CALLBACK WndProc(HWND hWnd, UINT messg,
WPARAM wParam, LPARAM lParam)
<
HDC hdc; //создаём идентификатор контекста устройства
//Цикл обработки сообщений
switch(messg)
<
//Обработка нажатия клавиши
case WM_KEYDOWN:
key=wParam; //Получаем код нажатой клавиши
_itoa(key, szText, 10); //Преобразуем его в строку
hdc=GetDC(hWnd); //Получаем контекст рисования
TextOut(hdc, 10,10, szText, 2); //Выводим текст на экран
break;
default:
return(DefWindowProc(hWnd, messg, wParam, lParam)); //освобождаем очередь приложения от нераспознаных
>
return 0;
>
case WM_KEYDOWN:
key=wParam; //Получаем код нажатой клавиши
_itoa(key, szText, 10); //Преобразуем его в строку
hdc=GetDC(hWnd); //Получаем контекст рисования
TextOut(hdc, 10,10, szText, 2); //Выводим текст на экран
break;
Мы присваиваем целой переменной key значение переменной wParam. После получения окном сообщения WM_KEYDOWN, оно записывает в него код нажатой клавиши. Так как это целое число, его необходимо преобразовать в строку, чтобы вывести на экран. Этим занимается функция _itoa, которая аналогична подобной функции DOS. После этого, в строке szText у нас будет код в виде строки, который не стыдно вывести на экран.
Допустим, нам нужно отловить сочетание Ctrl+S. Запустив программу, мы узнаём, что код этого сочетания = 83. Тогда наша первоначальная конструкция будет несколько видоизменена:
case WM_KEYDOWN:
key=wParam; //Получаем код нажатой клавиши
//Обработка нажатия клавиш
switch(key) <
case 83:
MessageBox(hWnd, «Ваше данные сохранены», «», MB_OK);
break;
//Здесь могут быть и другие case
>
Не правда ли это напоминает аналогичную DOS программу?
key=getch();
switch(key) <
case 83:
printf(«Данные сохранены!»);
break;
>
Какими далёкими кажутся теперь эти строки!
Теперь создадим программу, печатающую вводимые нами символы. Используем сообщение от WM_CHAR. Казалось, бы, зачем вообще нужно WM_CHAR, если есть WM_KEYDOWN? Ан нет! WM_CHAR полностью игнорирует нажимаемые нами клавиши, если это не символы букв и цифр. Это удобно, если мы хотим создать свой текстовый редактор или программу, получающую данные из строки ввода, как в DOS. Нам не надо писать подпрограмму, в которой фильтруются коды клавиш. Всё уже сделано за нас. Будет это выгледять так:
case WM_CHAR:
key=wParam;
wsprintf(szText, «%c», key);
hdc=GetDC(hWnd); //Получаем контекст рисования
TextOut(hdc, 10,10, szText, 1); //Выводим текст на экран
break;
Точно так же мы получаем код и записываем его в key. Затем используем функцию wsprintf, аналогичную sprintf в MS-DOS, копируя в строку символ. Затем выводим эту строку на экран. Закомментируйте в предыдущей программе сообщение WM_KEYDOWN и замените его этим. На экран будет выводиться по одному символу.
Если же вы хотите, чтобы каретка перемещалась, сделайте координаты TextOut динамичными. Пусть при нажатии клавиши, координата по X увеличивается, а при нажатии Enter увеличивается координата по y. Можно ещё отловить Return и обеспечить затирание введённого символа.
Так программа обрабатывает символьные клавиши.
По таблице виртульных клавиш вы всегда сможете узнать код нужной кнопки.
Таблица виртуальных клавиш.
WM_KEYDOWN message
Posted to the window with the keyboard focus when a nonsystem key is pressed. A nonsystem key is a key that is pressed when the ALT key is not pressed.
Parameters
The virtual-key code of the nonsystem key. See Virtual-Key Codes.
The repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag, as shown following.
Bits | Meaning |
---|---|
0-15 | The repeat count for the current message. The value is the number of times the keystroke is autorepeated as a result of the user holding down the key. If the keystroke is held long enough, multiple messages are sent. However, the repeat count is not cumulative. |
16-23 | The scan code. The value depends on the OEM. |
24 | Indicates whether the key is an extended key, such as the right-hand ALT and CTRL keys that appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key; otherwise, it is 0. |
25-28 | Reserved; do not use. |
29 | The context code. The value is always 0 for a WM_KEYDOWN message. |
30 | The previous key state. The value is 1 if the key is down before the message is sent, or it is zero if the key is up. |
31 | The transition state. The value is always 0 for a WM_KEYDOWN message. |
Return value
An application should return zero if it processes this message.
Example
Remarks
If the F10 key is pressed, the DefWindowProc function sets an internal flag. When DefWindowProc receives the WM_KEYUP message, the function checks whether the internal flag is set and, if so, sends a WM_SYSCOMMAND message to the top-level window. The WM_SYSCOMMAND parameter of the message is set to SC_KEYMENU.
Because of the autorepeat feature, more than one WM_KEYDOWN message may be posted before a WM_KEYUP message is posted. The previous key state (bit 30) can be used to determine whether the WM_KEYDOWN message indicates the first down transition or a repeated down transition.
For enhanced 101- and 102-key keyboards, extended keys are the right ALT and CTRL keys on the main section of the keyboard; the INS, DEL, HOME, END, PAGE UP, PAGE DOWN, and arrow keys in the clusters to the left of the numeric keypad; and the divide (/) and ENTER keys in the numeric keypad. Other keyboards may support the extended-key bit in the lParam parameter.
Applications must pass wParam to TranslateMessage without altering it at all.
Коды виртуальных клавиш
Нижеследующая таблица показывает названия именованных констант, шестнадцатеричные значения, и эквиваленты мыши или клавиатуры для кодов виртуальных клавиш, используемых системой. Коды перечисляются в нарастающем порядке.
Windows 2000/XP: для американской стандартной клавиатуры это клавиша ‘;:’.
Windows 2000/XP: для американской стандартной клавиатуры это клавиша ‘/?’.
Windows 2000/XP: для американской стандартной клавиатуры это клавиша ‘`
ввод с клавиатуры (Начало работы с Win32 и C++)
Клавиатура используется для нескольких различных типов входных данных, включая:
При обдумывании ввода с клавиатуры важно помнить, что сочетание клавиш не совпадает с символом. Например, при нажатии клавиши может появиться любой из следующих символов.
Кроме того, если клавиша ALT удерживается, нажатие клавиши вызывает ALT + A, который система не обрабатывает как символ, а вместо системной команды.
Коды клавиш
При нажатии клавиши оборудование создает код сканирования. Коды сканирования меняются от одной клавиатуры к следующей, и для событий ключа и нажатия клавиш существуют отдельные коды проверки. Вы почти не будете заботиться о кодах проверки. Драйвер клавиатуры преобразует коды проверки в коды виртуальных клавиш. Коды виртуальных клавиш не зависят от устройства. При нажатии клавиши на любой клавиатуре создается тот же код виртуального ключа.
В общем случае коды виртуальных клавиш не соответствуют кодам ASCII или любому другому стандарту кодировки символов. Это очевидно, если вы думаете о нем, так как один и тот же ключ может создавать разные символы (a, б), а некоторые ключи, такие как функциональные клавиши, не соответствуют какому-либо символу.
С другой стороны, следующие коды виртуальных клавиш соответствуют эквивалентам ASCII:
В некоторых отношениях это сопоставление относится к сожалению, поскольку в этом случае не следует думать о кодах виртуальных клавиш как символах, по указанным причинам.
Файл заголовка WinUser. h определяет константы для большинства кодов виртуальных клавиш. Например, код виртуального ключа для клавиши со стрелкой влево — VK _ Left (0x25). Полный список кодов виртуальных ключей см. в разделе коды виртуальных ключей. Для кодов виртуальных клавиш, соответствующих значениям ASCII, константы не определены. Например, код виртуального ключа для ключа — 0x41 влево, но нет константы с именем VK _ A. Вместо этого просто используйте числовое значение.
Сообщения Key-Down и Key-Up
При нажатии клавиши окно с фокусом клавиатуры получает одно из следующих сообщений.
Сообщение WM _ сискэйдовн указывает на системный ключ, который является ключевым росчерком, вызывающим системную команду. Существует два типа системного ключа:
Клавиша F10 активирует строку меню окна. Различные сочетания ALT-клавиш вызывают системные команды. Например, клавиши ALT + TAB переключились на новое окно. Кроме того, если окно содержит меню, клавишу ALT можно использовать для активации пунктов меню. Некоторые сочетания клавиш ALT не выполняют никаких действий.
При освобождении ключа система отправляет соответствующее сообщение о ключе:
Если удерживать ключ достаточно долго для запуска функции повтора клавиатуры, система отправляет несколько сообщений о ключах, за которыми следует одно сообщение о нажатии.
Во всех четырех описанных выше сообщениях клавиатуры параметр wParam содержит код виртуального ключа. Параметр lParam содержит некоторые прочие сведения, упакованные в 32 бит. Как правило, сведения не нужны в параметре lParam. Одним из флагов, которые могут быть полезны, является бит 30, флаг «предыдущее состояние ключа» которого имеет значение 1 для повторяющихся сообщений о нажатии клавиш.
Символьные сообщения
WM _ KEYDOWN: Shift
WM _ KEYDOWN: A
WM _ CHAR: ‘ A ‘
С другой стороны, сочетание ALT + P создаст следующее:
WM _ СИСКЭЙДОВН: _ меню VK
WM _ СИСКЭЙДОВН: 0x50
WM _ СИСЧАР: «p»
WM _ СИСКЭЙУП: 0x50
WM _ Клавиша вверх: VK _ меню
(Код виртуального ключа для клавиши ALT называется VK _ МЕНЮ по историческим причинам.)
Сообщение WM _ сисчар указывает системный символ. Как и в WM _ сискэйдовн, это сообщение обычно следует передавать непосредственно в дефвиндовпрок. В противном случае может возникнуть конфликт со стандартными системными командами. В частности, не следует рассматривать WM _ сисчар как текст, вводимый пользователем.
Сообщение WM _ char — это то, что обычно можно считать символьным вводом. Тип данных для символа — WCHAR _ t, представляющий символ Юникода UTF-16. Символьные данные могут содержать символы за пределами диапазона ASCII, особенно с раскладками клавиатуры, которые обычно используются за пределами США. Вы можете попробовать различные раскладки клавиатуры, установив региональную клавиатуру, а затем используя функцию экранной клавиатуры.
Пользователи также могут установить редактор метода ввода (IME) для ввода сложных наборов символов, таких как японские символы, с помощью стандартной клавиатуры. Например, используя японский редактор IME для ввода символа катакана カ (ка), вы можете получить следующие сообщения:
WM _ KEYDOWN: VK _ процесскэй (клавиша обработки IME)
WM _ Клавиша вверх: 0x4B
WM _ KEYDOWN: VK _ процесскэй
WM _ Клавиша вверх: 0x41 влево
WM _ KEYDOWN: VK _ процесскэй
WM _ CHAR: カ
WM _ Клавиша вверх: VK _ return
Некоторые сочетания клавиш CTRL преобразуются в управляющие символы ASCII. Например, CTRL + A преобразуется в символ ASCII CTRL-A (SOH) (значение ASCII 0x01). Для ввода текста обычно следует отфильтровывать управляющие символы. Кроме того, не следует использовать WM _ char для реализации сочетаний клавиш. Вместо этого используйте сообщения с помощью WM _ KeyDown или еще лучше, используя таблицу сочетаний клавиш. Таблицы ускорителей описаны в следующем разделе: таблицы сочетаний клавиш.
В следующем коде отображаются основные сообщения клавиатуры в отладчике. Попробуйте воспроизвести различные сочетания клавиш и посмотрите, какие сообщения создаются.
Различные сообщения клавиатуры
Большинство приложений могут спокойно игнорировать некоторые другие сообщения клавиатуры.
Состояние клавиатуры
Например, рассмотрим, как можно определить сочетание левой кнопки мыши + ALT. Вы можете отвести состояние клавиши ALT, прослушивая сообщения о нажатии клавиш и сохранив флаг, но жеткэйстате экономит проблемы. При получении сообщения WM _ лбуттондовн просто вызовите жеткэйстате следующим образом:
Сообщение жеткэйстате принимает в качестве входных данных код виртуального ключа и возвращает набор битовых флагов (на самом деле только два флага). Значение 0x8000 содержит битовый флаг, который проверяет, нажата ли клавиша в данный момент.
Большинство клавиатур имеют две клавиши ALT слева и справа. В предыдущем примере проверяется, была ли нажата одна из них. Можно также использовать жеткэйстате для различения левого и правого экземпляров клавиш ALT, Shift или CTRL. Например, следующий код проверяет, нажата ли правая клавиша ALT.
Функция жеткэйстате является интересной, так как она сообщает о состоянии виртуальной клавиатуры. Это виртуальное состояние основано на содержимом очереди сообщений и обновляется при удалении сообщений из очереди. По мере того как программа обрабатывает сообщения окна, жеткэйстате предоставляет моментальный снимок клавиатуры во время постановки каждого сообщения в очередь. Например, если Последнее сообщение в очереди — WM _ лбуттондовн, жеткэйстате сообщает о состоянии клавиатуры в момент нажатия пользователем кнопки мыши.
Так как жеткэйстате основан на очереди сообщений, она также игнорирует ввод с клавиатуры, отправленный в другую программу. Если пользователь переключается на другую программу, любые нажатия клавиш, отправленные в эту программу, игнорируются жеткэйстате. Если вы действительно хотите получить немедленное физическое состояние клавиатуры, существует функция для этого: жетасинккэйстате. Однако для большинства кода пользовательского интерфейса правильная функция — жеткэйстате.
Операционная система Microsoft Windows 3.1 для программиста
5.2. Параметры клавиатурных сообщений
Сообщения WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP передают информацию о нажатой клавише через параметры lParam и wParam.
Параметр lParam для этих сообщений содержит информацию низкого уровня, такую, как скан-код, счетчик повторов, флаг предыдущего состояния клавиши и т. п. Эта информация редко используется приложениями Windows.
Параметр wParam содержит код виртуальной клавиши, соответствующей нажатой физической клавише. Именно этот параметр используется приложениями для идентификации нажатой клавиши.
Приведем описание отдельных бит парамера lParam.
Если нажать клавишу и оставить ее в нажатом состоянии, функция окна может получить подряд несколько сообщений WM_KEYDOWN, прежде чем придет сообщение WM_KEYUP. В этом случае бит предыдущего состояния клавиши (бит 30) можно использовать для обнаружения сообщений, возникших в результате включения автоповтора клавиатуры. Приложение может игнорировать такие сообщения, исключая эффект накопления, когда приложение не может обрабатывать сообщения с такой скоростью, с какой они поступают. Например, если вы будете долго держать клавишу пролистывания страниц в текстовом редакторе, то после того, как вы ее отпустите, текстовый редактор будет еще долго листать ваш документ.
Для сообщений WM_KEYDOWN и WM_KEYUP значение кода контекста (бит 29) и флага изменения состояния (бит 31) всегда равно 0.
Для сообщений WM_SYSKEYUP и WM_SYSKEYDOWN бит 31 равен 1. Но есть два исключения.
Во-первых, если активное окно свернуто в пиктограмму, все сообщения от клавиатуры преобразовываются в системные и, если клавиша не нажата, код контекста равен 0.
Обработчик клавиатурного сообщения должен возвратить значение 0 для всех перехваченных сообщений.
Теперь мы расскажем вам о параметре wParam.
Как мы уже говорили, этот параметр содержит код виртуальной клавиши, соответствующей нажатой физической клавише. Код виртуальной клавиши не зависит от аппаратной реализации клавиатуры.
Многие коды виртуальных клавиш имеют символьное обозначение, определенное в файле windows.h. Приведем полный список кодов виртуальных клавиш. Те из них, которые определены в файле windows.h, имеют префикс VK_ (от слов Virtual Key).
Рассматривая приведенную выше таблицу, нетрудно заметить, что в ней есть коды виртуальных клавиш, которые невозможно получить в компьютере с IBM-совместимой клавиатурой. Кроме того, используя только эти коды, невозможно различить строчные и прописные буквы.
Параметр функции vkey должен указывать код виртуальной клавиши, для которой необходимо вернуть состояние.
Старший бит возвращаемого значения, установленный в 1, говорит о том, что указанная клавиша была нажата. Если этот бит равен 0, клавиша не была нажата.
Младший бит возвращаемого значения указывает состояние переключения. Если он равен 1, клавиша (такая, как или ) находится во включенном состоянии, то есть она была нажата нечетное число раз после включения компьютера. Учтите, что при помощи программы установки параметров компьютера SETUP, расположенной в BIOS, вы можете задать произвольное состояние переключающих клавиш после запуска системы.
Функция GetKeyState возвращает состояние клавиши на момент извлечения сообщения из очереди приложения функцией GetMessage.
Параметр функции vkey должен указывать код виртуальной клавиши, для которой необходимо вернуть состояние.
Старший бит возвращаемого значения, установленный в 1, говорит о том, что указанная клавиша была нажата в момент вызова функции. Если этот бит равен 0, клавиша не была нажата.
Младший бит возвращаемого значения установлен в 1, если указанная клавиша была нажата с момента последнего вызова функции GetAsyncKeyState.
Если для функции в качестве параметра задать значения VK_LBUTTON или VK_RBUTTON, можно узнать состояние клавиш, расположенных на корпусе мыши.
Есть возможность определить и изменить состояние для всех клавиш одновременно.
Для определения состояния клавиш воспользуйтесь функцией GetKeyboardState:
Для любого байта массива установленный в 1 старший бит означает, что соответствующая клавиша была нажата. Если этот бит равен 0, клавиша не была нажата. Младший бит, установленный в 1, означает, что клавиша была переключена. Если младший бит равен 0, клавиша не была переключена.
После вызова функции GetKeyboardState вы можете изменить содержимое массива и вызвать функцию SetKeyboardState, изменяющую состояние клавиатуры:
Функция GetKeyboardType позволит вам определить тип клавиатуры и количество имеющихся на ней функциональных клавиш:
В зависимости от значения параметра fnKeybInfo функция может возвращать различную информацию о клавиатуре.
Если задать значение параметра fnKeybInfo, равное 0, функция вернет код типа клавиатуры:
Код | Тип клавиатуры | Количество функциональных клавиш |
1 | Клавиатура IBM PC/XT или совместимая, 83-клавишная | 10 |
2 | Клавиатура Olivetti «ICO», 102-клавишная | 12 (иногда 18) |
3 | Клавиатура IBM AT или аналогичная, 84-клавишная | 10 |
4 | Клавиатура IBM Enhanced (улучшенная), 101- или 102-клавишная | 12 |
5 | Клавиатура Nokia 1050 или аналогичная | 10 |
6 | Клавиатура Nokia 9140 или аналогичная | 24 |
7 | Японская клавиатура | Зависит от аппаратуры |
Если задать значение параметра, равное 1, функция вернет код подтипа клавиатуры.
И наконец, если задать значение параметра, равное 2, функция вернет количество функциональных клавиш, имеющихся на клавиатуре.
Интересна также функция GetKeyNameText, возвращающая для заданного кода виртуальной клавиши название соответствующей клавиши в виде текстовой строки. Названия виртуальных клавиш определены в драйвере клавиатуры.
Приведем прототип функции GetKeyNameText:
Первый параметр функции lParam должен определять клавишу в формате компоненты lParam клавиатурного сообщения. Вы можете использовать в качестве этого параметра значение lParam, полученное функцией окна вместе с любым клавиатурным сообщением, таким, как WM_KEYDOWN или WM_SYSKEYDOWN.
Приведем исходный текст приложения KBTYPE, определяющего тип и подтип клавиатуры, а также количество функциональных клавиш (листинг 5.1).
Листинг 5.1. Файл kbtype\kbtype.cpp
Приложение использует файл определения модуля, приведенный в листинге 5.2.
Листинг 5.2. Файл kbtype\kbtype.def
Работа приложения KBTYPE понятна без дополнительных комментариев. Единственное, на чем нам хотелось бы остановиться, так это на использовании для подготовки текстового буфера функции wsprintf.
Функция wsprintf входит в ядро Windows и используется аналогично функции sprintf. Эта функция определена в файле windows.h следующим образом:
Первый параметр функции является дальним указателем на буфер, в который будет записана сформированная текстовая строка, закрытая двоичным нулем.
Спецификатор | Формат |
c | Один символ |
d, i | Целое число со знаком |
ld, li | Двойное целое число со знаком |
u | Целое число без знака |
lu | Двойное целое число без знака |
lx, lX | Двойное целое число без знака в шестнадцатеричном формате строчными или прописными буквами |
s | Текстовая строка |
Далее следует произвольное число переменных, описанных в строке формата. Так как функции передается переменное число параметров, она (в отличие от подавляющего большинства функций программного интерфейса Windows) использует для передачи параметров соглашение языка Си, а не Паскаль.
Для вывода текстовых строк необходимо использовать явное преобразование типа, как это сделано в нашем примере:
Функция возвращает количество байт, записанных в выходной буфер, без учета двоичного нуля, закрывающего текстовую строку.
На рис. 5.1 представлено сообщение, которое было выведено при запуске приложения KBTYPE на компьютере одного из авторов этой книги.
Рис. 5.1. Сообщение приложения KBTYPE
Листинг 5.3. Файл kbled\kbled.cpp
Это простое приложение выводит на экран сообщение, в котором говорится, что для переключения состояния виртуальных клавиш надо нажать кнопку «OK». Когда вы нажмете эту кнопку, состояние трех виртуальных клавиш изменится на противоположное. Это нетрудно проконтролировать при помощи светодиодов, расположенных на клавиатуре: все они должны изменить свое состояние на противоположное.
Когда вы ответите на второе сообщение, приложение возвратит исходное состояние клавиш (и светодиодов).
Файл определения модуля для приложения KBLED приведен в листинге 5.4.
- С чем сделать ванночку для ног перед педикюром
- 0x80070422 код ошибки 0x80070422 windows 10 как исправить