Ввод с клавиатуры (начало работы с Win32 и C++)
Клавиатура используется для нескольких различных типов ввода, в том числе:
- Ввод символов. Текст, который пользователь вводит в документ или поле редактирования.
- Сочетания клавиш. Росчерки клавиш, вызывающие функции приложения; Например, нажмите клавиши CTRL+O, чтобы открыть файл.
- Системные команды. Росчерки клавиш, вызывающие системные функции; например, ALT+TAB для переключения окон.
При вводе с клавиатуры важно помнить, что нажатие клавиши не совпадает с символом. Например, нажатие клавиши A может привести к любому из следующих символов.
- а
- Объект
- á (если клавиатура поддерживает объединение диакритических элементов)
Кроме того, если клавиша ALT удерживается, нажатие клавиши A приведет к возникновению клавиш ALT+A, которые система обрабатывает не как символ, а как системную команду.
Коды ключей
При нажатии клавиши оборудование создает код сканирования. Коды сканирования зависят от клавиатуры к другой, и существуют отдельные коды сканирования для событий нажатия клавиш и нажатия клавиш. Вы почти никогда не будете заботиться о кодах сканирования. Драйвер клавиатуры преобразует коды сканирования в коды виртуальной клавиши. Коды виртуальных ключей не зависят от устройств. При нажатии клавиши A на любой клавиатуре создается тот же код виртуальной клавиши.
Как правило, коды виртуальных ключей не соответствуют кодам ASCII или любому другому стандарту кодировки символов. Это очевидно, если вы думаете, потому что один и тот же ключ может генерировать разные символы (a, A, á), а некоторые клавиши, например функциональные клавиши, не соответствуют ни одному символу.
При этом следующие коды виртуальных ключей сопоставляют с эквивалентами ASCII:
- От 0 до 9 клавиш = ASCII '0' – '9' (0x30 – 0x39)
- Клавиши A–Z = ASCII "A" – "Z" (0x41 – 0x5A)
В некоторых отношениях это сопоставление является неудачным, так как никогда не следует рассматривать коды виртуальных ключей как символы по рассматриваемым причинам.
Файл заголовка WinUser.h определяет константы для большинства кодов виртуальных ключей. Например, код виртуального ключа для клавиши СТРЕЛКА ВЛЕВО VK_LEFT (0x25). Полный список кодов виртуальных ключей см. в разделе Коды виртуальных ключей. Для кодов виртуальных ключей, соответствующих значениям ASCII, константы не определены. Например, код виртуального ключа для ключа A 0x41, но константы с именем VK_A нет. Вместо этого используйте просто числовое значение.
сообщения Key-Down и Key-Up
При нажатии клавиши окно с фокусом клавиатуры получает одно из следующих сообщений.
Сообщение WM_SYSKEYDOWN указывает системный ключ, который является росчерком ключа, который вызывает системную команду. Существует два типа системных ключей:
- ALT + любая клавиша
- F10
Клавиша F10 активирует строку меню окна. Различные сочетания клавиш ALT вызывают системные команды. Например, ALT+TAB переключается в новое окно. Кроме того, если в окне есть меню, для активации пунктов меню можно использовать клавишу ALT. Некоторые сочетания клавиш ALT ничего не делают.
Все остальные росчерки клавиш считаются несистемными ключами и создают WM_KEYDOWN сообщение. Сюда входят функциональные ключи, отличные от F10.
При освобождении ключа система отправляет соответствующее сообщение о ключе:
Если вы удерживаете клавишу достаточно долго, чтобы запустить функцию повторения клавиатуры, система отправляет несколько сообщений вниз, а затем одно сообщение клавиши вверх.
Во всех четырех сообщениях клавиатуры, рассмотренных на данный момент, параметр wParam содержит код виртуальной клавиши. Параметр lParam содержит некоторые прочие сведения, упакованные в 32 бита. Как правило, информация в lParam не требуется. Один из флагов, который может быть полезен, — бит 30, флаг "предыдущее состояние ключа", который имеет значение 1 для повторяющихся сообщений о нажатии клавиши.
Как следует из названия, росчерки системных ключей в первую очередь предназначены для использования операционной системой. При перехвате сообщения WM_SYSKEYDOWN вызовите DefWindowProc . В противном случае вы заблокируйте обработку команды операционной системой.
Символьные сообщения
Ключевые штрихи преобразуются в символы с помощью функции TranslateMessage , которую мы впервые видели в модуле 1. Эта функция проверяет сообщения, отправляемые клавишами, и преобразует их в символы. Для каждого создаваемого символа функция TranslateMessage помещает WM_CHAR или WM_SYSCHAR сообщение в очередь сообщений окна. Параметр wParam сообщения содержит символ UTF-16.
Как можно догадаться, WM_CHAR сообщения создаются из WM_KEYDOWN сообщений, а WM_SYSCHAR — из WM_SYSKEYDOWN сообщений. Например, предположим, что пользователь нажимает клавишу SHIFT, а затем клавишу A. Предполагая стандартную раскладку клавиатуры, вы получите следующую последовательность сообщений:
WM_KEYDOWN: SHIFT
WM_KEYDOWN: A
WM_CHAR: "A"
С другой стороны, сочетание ALT+P создаст следующее:
WM_SYSKEYDOWN: VK_MENU
WM_SYSKEYDOWN: 0x50
WM_SYSCHAR: "p"
WM_SYSKEYUP: 0x50
WM_KEYUP: VK_MENU
(Код виртуального ключа для клавиши ALT называется VK_MENU по историческим причинам.)
Сообщение WM_SYSCHAR указывает системный символ. Как и в случае с WM_SYSKEYDOWN, обычно это сообщение следует передавать непосредственно в DefWindowProc. В противном случае вы можете помешать стандартным системным командам. В частности, не следует рассматривать WM_SYSCHAR как текст, введенный пользователем.
Сообщение WM_CHAR обычно считается символьным вводом. Тип данных для символа — wchar_t, представляющий символ Юникода UTF-16. Ввод символов может включать символы за пределами диапазона ASCII, особенно с раскладками клавиатуры, которые обычно используются за пределами США. Вы можете попробовать различные раскладки клавиатуры, установив региональную клавиатуру, а затем используя функцию экранной клавиатуры.
Пользователи также могут установить редактор метода ввода (IME) для ввода сложных скриптов, таких как японские символы, с помощью стандартной клавиатуры. Например, с помощью японского редактора IME для ввода символа катаканы カ (ka) могут появиться следующие сообщения:
WM_KEYDOWN: VK_PROCESSKEY (клавиша IME PROCESS)
WM_KEYUP: 0x4B
WM_KEYDOWN: VK_PROCESSKEY
WM_KEYUP: 0x41
WM_KEYDOWN: VK_PROCESSKEY
WM_CHAR: カ
WM_KEYUP: VK_RETURN
Некоторые сочетания клавиш CTRL претворяются в управляющие символы ASCII. Например, СОЧЕТАНИЕ КЛАВИШ CTRL+A преобразуется в символ ASCII CTRL-A (SOH) (значение ASCII 0x01). Для ввода текста обычно следует отфильтровать управляющие символы. Кроме того, не используйте WM_CHAR для реализации сочетаний клавиш. Вместо этого используйте WM_KEYDOWN сообщения; или, что еще лучше, используйте таблицу ускорителей. Таблицы ускорителей описаны в следующем разделе Таблицы ускорителей.
В следующем коде отображаются сообщения main клавиатуры в отладчике. Попробуйте играть с различными сочетаниями нажатий клавиш и посмотреть, какие сообщения создаются.
Примечание
Обязательно включите wchar.h, иначе swprintf_s будет неопределенным.
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
wchar_t msg[32];
switch (uMsg)
{
case WM_SYSKEYDOWN:
swprintf_s(msg, L"WM_SYSKEYDOWN: 0x%x\n", wParam);
OutputDebugString(msg);
break;
case WM_SYSCHAR:
swprintf_s(msg, L"WM_SYSCHAR: %c\n", (wchar_t)wParam);
OutputDebugString(msg);
break;
case WM_SYSKEYUP:
swprintf_s(msg, L"WM_SYSKEYUP: 0x%x\n", wParam);
OutputDebugString(msg);
break;
case WM_KEYDOWN:
swprintf_s(msg, L"WM_KEYDOWN: 0x%x\n", wParam);
OutputDebugString(msg);
break;
case WM_KEYUP:
swprintf_s(msg, L"WM_KEYUP: 0x%x\n", wParam);
OutputDebugString(msg);
break;
case WM_CHAR:
swprintf_s(msg, L"WM_CHAR: %c\n", (wchar_t)wParam);
OutputDebugString(msg);
break;
/* Handle other messages (not shown) */
}
return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}
Прочие сообщения клавиатуры
Некоторые другие сообщения клавиатуры можно игнорировать в большинстве приложений.
- Сообщение WM_DEADCHAR отправляется для комбинирования ключа, например для диакритического ключа. Например, на испанской клавиатуре при вводе акцента (') и E создается символ é. Для символа акцента отправляется WM_DEADCHAR.
- Сообщение WM_UNICHAR устарело. Это позволяет программам ANSI получать входные данные в Юникоде.
- Символ WM_IME_CHAR отправляется, когда IME преобразует последовательность нажатия клавиш в символы. Оно отправляется в дополнение к обычному WM_CHAR сообщению.
Состояние клавиатуры
Сообщения клавиатуры управляются событиями. То есть вы получите сообщение, когда происходит что-то интересное, например нажатие клавиши, и сообщение сообщает вам, что только что произошло. Но вы также можете проверить состояние ключа в любое время, вызвав функцию GetKeyState .
Например, рассмотрим, как определить сочетание щелчка левой кнопкой мыши и клавиши ALT. Вы можете отслеживать состояние клавиши ALT, прослушивая сообщения об росчерке клавиш и сохраняя флаг, но GetKeyState избавляет вас от проблем. Когда вы получите сообщение WM_LBUTTONDOWN , просто вызовите GetKeyState следующим образом:
if (GetKeyState(VK_MENU) & 0x8000)
{
// ALT key is down.
}
Сообщение GetKeyState принимает код виртуального ключа в качестве входных данных и возвращает набор битовых флагов (на самом деле всего два флага). Значение 0x8000 содержит битовый флаг, который проверяет, нажата ли клавиша в данный момент.
Большинство клавиатур имеет две клавиши ALT: левую и правую. В предыдущем примере проверяется, был ли нажат любой из них. Вы также можете использовать GetKeyState , чтобы различать левый и правый экземпляры клавиш ALT, SHIFT или CTRL. Например, следующий код проверяет, нажата ли правая клавиша ALT.
if (GetKeyState(VK_RMENU) & 0x8000)
{
// Right ALT key is down.
}
Функция GetKeyState интересна тем, что она сообщает о состоянии виртуальной клавиатуры. Это виртуальное состояние основано на содержимом очереди сообщений и обновляется при удалении сообщений из очереди. По мере обработки сообщений окна программа GetKeyState предоставляет snapshot клавиатуры во время постановки каждого сообщения в очередь. Например, если последнее сообщение в очереди было WM_LBUTTONDOWN, GetKeyState сообщает о состоянии клавиатуры в тот момент, когда пользователь нажал кнопку мыши.
Так как GetKeyState основан на очереди сообщений, он также игнорирует ввод с помощью клавиатуры, отправленный в другую программу. Если пользователь переключается на другую программу, все нажатия клавиш, отправляемые в нее, игнорируются Командлетом GetKeyState. Если вы действительно хотите узнать непосредственное физическое состояние клавиатуры, для этого есть функция : GetAsyncKeyState. Однако для большинства кода пользовательского интерфейса правильная функция — GetKeyState.
Следующая