
- •Оглавление
- •1 Простейшее Win32 приложение
- •2 Функция WinMain
- •3 Оконный класс
- •4 Стили класса, стили окна
- •5 Создание экземпляра оконного класса
- •6 Динамические изменения свойств оконного класса
- •7 Обработка сообщений
- •8 Программирование клавиатуры
- •9 Коды oem, ansii, asci, виртуальные коды клавиш
- •10 Символьные сообщения
- •11 Обработка сообщений от мыши
- •12 Программирование таймера
- •13 Диалоговые окна
- •14 Структура шаблона диалога
- •14(А) Ресурсы диалога
- •15 Функции создания диалога
- •16 Взаимодействие между элементами управления
- •17 Сообщения, SendMessage, SendDlgItemMessage
- •18 Обработка сообщений от элементов диалога
- •19 Элемент «Слайдер» (Румянцев - Азбука программирования в Win32 api, c.148)
- •20 Элемент ProgressBar (Румянцев - Азбука программирования в Win32 api, c.156)
- •21 Bios (общие сведения)
- •22 Файлы (общие сведения)
- •23 Создание файла (Win32 api)
- •24 Операции с файлом (Win32 api)
- •25 Организация файлов
- •26 Файловые системы (общие сведения)
- •Создание файла.
- •Удаление файла.
- •28 Структура логического диска под fat12 (wfat)
- •29 Каталоги в fat12
- •30 Алгоритм определения расположения файлов на диске
- •31 Ф.С. Fat32 (отличительные особенности)
- •32 Изменение элементов системных объектов при выполнении copy
- •33 Ntfs (общие сведения)
- •34 Запись файла в mft
- •35 Метафайлы
- •36 Атрибуты записи файла
- •37 Изменение системных данных при выполнении copy
- •38 Изменение системных данных при выполнении del
- •39 Изменение системных данных при выполнении move
- •40 Процессы. Потоки. Общие сведения
- •41 Модель процесса
- •42 Контекст процесса
- •43 Дескриптор процесса
- •44 Создание процесса (общие сведения)
- •45 Окончание процесса (общие сведения)
- •46 Состояния процесса
- •47 Уровни планирования процессов
- •48 Диспетчеризация процессов
- •49 Класс приоритета процесса
- •50 Создание процесса (Win32 api)
- •51 Win32 Api. Управление процессами
- •52 Win32 Api. Окончание процесса
- •53 Среда процесса
- •54 Командная строка процесса
- •55 Наследование дочерними процессами ресурсов родителя
- •56 Список процессов
- •57 Время выполнения процесса
8 Программирование клавиатуры
Основанная на сообщениях архитектура Windows идеальна для работы с клавиатурой.
Приложение
узнает о нажатиях клавиш посредством
сообщений, которые посылаются оконной
процедуре. Когда
пользователь нажимает и отпускает
клавиши,
Драйвер клавиатуры передает информацию о нажатии клавиш в Windows.
Windows сохраняет эту информацию (в виде сообщений) в системной очереди сообщений.
Затем она передает сообщения клавиатуры, по одному за раз, в очередь сообщений программы, содержащей окно, имеющее фокус ввода (input focus).
Затем программа отправляет сообщения соответствующей оконной процедуре (с помощью функции DispatchMessage).
Смысл этого двухступенчатого процесса – сохранение сообщений в системной очереди сообщений и дальнейшая их передача в очередь сообщений приложения – в синхронизации.
Если пользователь печатает на клавиатуре быстрее, чем программа может обрабатывать поступающую информацию, Windows сохраняет информацию о дополнительных нажатиях клавиш в системной очереди сообщений, поскольку одно из дополнительных нажатий может быть переключением фокуса ввода на другую программу. Информацию о последующих нажатиях следует затем направлять в другую программу. Таким образом, Windows корректно синхронизирует такие события клавиатуры.
Для отражения различных событий клавиатуры Windows посылает программам восемь различных сообщений. Программы вполне могут игнорировать многие из них; кроме того, в большинстве случаев, в этих сообщениях от клавиатуры содержится значительно больше закодированной информации, чем нужно приложению.
Сообщения, которые приложение получает от Windows о событиях, относящихся к клавиатуре, различаются на аппаратные (keystrokes) и символьные (characters). Такое положение соответствует двум представлениям о клавиатуре.
Во-первых, клавиатуру можно считать набором клавиш. В клавиатуре имеется только одна клавиша <A>. Нажатие на эту клавишу является аппаратным событием; отпускание этой клавиши является аппаратным событием.
Во-вторых, клавиатура также является устройством ввода, генерирующим отображаемые символы. Клавиша <A>, в зависимости от состояния клавиш <Ctrl>, <Shift> и <CapsLock>, может стать источником нескольких символов. Обычно, этим сомволом является строчное ‘a’. Если же нажата клавиша <Shift> или установлен режим <CapsLock>, то этим символом является прописное ‘A’. Если нажата клавиша <Ctrl>, этим символом является <Ctrl+A>.
Для сочетаний двух аппаратных событий, которые генерируют отображаемые символы, Windows посылает программе и оба аппаратных и символьное сообщение.
Некоторые клавиши не генерируют символов. Это такие клавиши, как клавиши переключения, функциональные клавиши, клавиши управления курсором и специальные клавиши, такие как <Insert> и <Delete>. Для таких клавиш Windows вырабатывает только аппаратные сообщения.
Аппаратные сообщения
Когда пользователь нажимает клавишу, Windows помещает либо сообщение WM_KEYDOWN, либо сообщение WM_SYSKEYDOWN в очередь сообщений окна, имеющего фокус ввода. Когда клавиша отпускается, Windows помещает в очередь сообщений либо сообщение WM_KEYUP, либо сообщение WM_SYSKEYUP.
Итак,
Несистемные аппаратные сообщения – это сообщения WM_KEYDOWN и WM_KEYUP, а системные - WM_SYSKEYDOWN и WM_SYSKEYUP.
Системные аппаратные сообщения WM_SYSKEYDOWN и WM_SYSKEYUP более важны для Windows, чем для приложений.
Эти сообщения обычно вырабатываются при нажатии клавиш в сочетании с клавишей <Alt>. Эти сообщения вызывают опции меню программы или системного меню, или используются для системных функций, таких как смена активного приложения (<Alt+Tab>).
Программы обычно игнорируют сообщения WM_SYSKEYDOWN и WM_SYSKEYUP и передают их в функцию DefWindowProc. Оконная процедура, в конце концов, получает другие сообщения, являющиеся результатом этих аппаратных сообщений клавиатуры (например, выбор меню).
При необходимости же включить в код программы инструкции для обработки системных аппаратных сообщений клавиатуры следует после обработки этих сообщений передать их в DefWindowProc, чтобы Windows могла по-прежнему их использовать в обычных целях:
case WM_SYSKEYDOWN:
MessageBox(hWnd,”Message WM_SYSKEYDOWN”,”Key”,MB_OK);
return(DefWindowProc(hWnd,message,wParam,lParam));
case WM_SYSKEYUP:
MessageBox(hWnd,”Message WM_SYSKEYUP”,”Key”,MB_OK);
return(DefWindowProc(hWnd,message,wParam,lParam));
Замечание.
Рассмотрим,
что произойдет, если не передать системные
аппаратные сообщения в DefWindowProc.
Почти все, что влияет на окно программы,
в первую проходит через оконную процедуру.
Windows самостоятельно обрабатывает
сообщения только в том случае, если они
передаются в DefWindowProc.
Например, пусть при обработке пришедшего в оконную процедуру сообщения добавлены строки для следующей обработки системных сообщений:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_SYSCHAR:
return 0;
При этом происходит запрет всех операций с клавишей <Alt> (команды меню, <Alt+Tab> и др.), когда окно программы имеет фокус ввода.
Несистемные сообщения WM_KEYDOWN и WM_KEYUP обычно вырабатываются для клавиш, которые нажимаются и отпускаются без участия клавиши <Alt>. Приложение может использовать или не использовать эти сообщения клавиатуры. Сама Windows их проигнорирует.
Обычно сообщения о нажатии и отпускании появляются парами. Однако если пользователь оставит клавишу нажатой так, чтобы включился автоповтор, то Windows посылает оконной процедуре серию сообщений WM_KEYDOWN (или WM_SYSKEYDOWN) и одно сообщение WM_KEYUP (или WM_SYSKEYUP), когда, в конце концов, клавиша будет отпущена.
Также как и все синхронные сообщения, аппаратные сообщения клавиатуры также становятся в очередь. Приложение с помощью функции GetMessageTime получить время нажатия и отпускания клавиши относительно старта системы.
Символьные сообщения
Ранее рассматривалась идея преобразования аппаратных сообщений клавиатуры в символьные сообщения путем учета информации о положении клавиш сдвига и предупреждалось, что информации о положении этих клавиш недостаточно: вам необходимо также знать об особенностях реализации вашей национальной клавиатуры. По этой причине вам не следует пытаться самостоятельно преобразовывать аппаратные сообщения клавиатуры в
символьные коды. Для вас это делает Windows. Вы уже встречали такой код раньше:
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Это типичный цикл обработки сообщений, содержащийся в WinMain. Функция GetMessage заполняет поля структуры msg данными следующего сообщения из очереди. Вызов DispatchMessage вызывает соответствующую оконную процедуру.
Между двумя этими функциями находится функция TranslateMessage, преобразующая аппаратные сообщения клавиатуры в символьные сообщения. Если этим сообщением является WM_KEYDOWN или WM_SYSKEYDOWN и, если нажатие клавиши в сочетании с положением клавиши сдвига генерирует символ, тогда TranslateMessage помещает символьное сообщение в очередь сообщений. Это символьное сообщение будет следующим, после сообщения о нажатии клавиши, которое функция GetMessage извлечет из очереди сообщений. Существует четыре символьных сообщения:
Символы Немые символы
Несистемные символы: WM_CHAR WM_DEADCHAR
Системные символы: WM_SYSCHAR WM_SYSDEADCHAR
Сообщения WM_CHAR и WM_DEADCHAR являются следствием сообщений WM_KEYDOWN. Сообщения WM_SYSCHAR и WM_SYSDEADCHAR являются следствием сообщений WM_SYSKEYDOWN. В большинстве случаев ваши программы для Windows могут игнорировать все сообщения, за исключением WM_CHAR. Параметр lParam, передаваемый в оконную процедуру как часть символьного сообщения, является таким же, как параметр lParam аппаратного сообщения клавиатуры, из которого сгенерировано символьное сообщение. Параметр wParam — это код символа ASCII. Символьные сообщения доставляются в вашу оконную процедуру в промежутке между аппаратными сообщениями клавиатуры. Например, если переключатель <CapsLock> не включен и вы нажимаете и отпускаете клавишу <А>, оконная процедура получит три следующих сообщения:
Сообщение Клавиша или код
WM_KEYDOWN Виртуальная клавиша А
WM_CHAR ASCII код а
WM_KEYUP Виртуальная клавиша А
Если вы набираете прописное ‘А’, удерживая клавишу <Shift>, нажимая клавишу <А>, отпуская клавишу <А>, и затем отпуская клавишу <Shift>, оконная процедура получит пять сообщений:
Сообщение Клавиша или код
WM_KEYDOWN Виртуальная клавиша VK_SHIFT
WM_KEYDOWN Виртуальная клавиша А
WM_CHAR ASCII код А
WM_KEYUP Виртуальная клавиша А
WM_KEYUP Виртуальная клавиша VK_SHIFT
Сама по себе клавиша <Shift> не вырабатывает символьного сообщения. Если вы удерживаете клавишу <А> нажатой так, что автоповтор генерирует аппаратные сообщения клавиатуры, то
на каждое сообщение WM_KEYDOWN, вы получите символьное сообщение:
Сообщение Клавиша или код
WM_KEYDOWN Виртуальная клавиша А
WM_CHAR ASCII код А
WM_KEYDOWN Виртуальная клавиша А
WM_CHAR ASCII код А
WM_KEYDOWN Виртуальная клавиша А
WM_CHAR ASCII код А
WM_KEYDOWN Виртуальная клавиша А
WM_CHAR ASCII код А
WM_KEYUP Виртуальная клавиша А
Если у некоторых сообщений WM_KEYDOWN счетчик повторений больше 1, то у соответствующих сообщений WM_CHAR счетчик повторений будет иметь то же значение. Клавиша <Ctrl> в сочетании с буквенной клавишей генерирует управляющие коды ASCII от 01H (<Ctrl>+<A>) до 1AH (<Ctrl>+<Z>). Для выработки таких управляющих кодов вы можете также использовать и другие клавиши.
В программах для Windows клавиша <Ctrl> иногда используется с клавишами букв в качестве быстрых клавиш, в таком случае сообщения от буквенных клавиш не преобразуются в символьные сообщения.
Сообщения WM_CHAR
Если вашей Windows-программе необходимо обрабатывать символы клавиатуры (например, в программах обработки текстов или коммуникационных программах), то она будет обрабатывать сообщения WM_CHAR.
case WM_CHAR:
switch(wParam)
{
case '\b': // забой(Backspace)
186
[другие строки программы]
break;
case '\t': // табуляция(Tab)
[другие строки программы]
break;
case '\n': // перевод строки(Linefeed)
[другие строки программы]
break;
case '\r': // возврат каретки(Enter)
[другие строки программы]
break;
default: // символьный код
[другие строки программы]
break;
}
return 0;
Этот фрагмент программы фактически идентичен обработке символов клавиатуры в обычных программах MS_DOS.
Сообщения немых символов
Программы для Windows обычно могут игнорировать сообщения WM_DEADCHAR и WM_SYSDEADCHAR. На некоторых, не американских клавиатурах, некоторые клавиши определяются добавлением диакритического знака к букве. Они называются "немыми клавишами" (dead keys), поскольку эти клавиши сами по себе не определяют символов. Например, при инсталляции немецкой клавиатуры, клавиша, находящаяся там же, где в американской клавиатуре находится клавиша <+/=>, становится немой клавишей для указания высокого звука (′), при ненажатой клавише сдвига, и низкого звука (`), при нажатой клавише сдвига. Если пользователь нажимает немую клавишу, оконная процедура получает сообщение WM_DEADCHAR с параметром wParam равным коду ASCII самого диакритического знака. Когда затем пользователь нажимает клавишу буквы (например, клавишу <А>), оконная процедура получает сообщение WM_CHAR, где параметр wParam равен коду ASCII буквы с диакритическим знаком. Таким образом, ваша программа не должна обрабатывать сообщение WM_DEADCHAR, поскольку сообщение WM_CHAR и так дает программе всю необходимую информацию. Windows имеет даже встроенную систему отслеживания ошибок: если за немой клавишей следует буква, у которой не может быть диакритического знака (например буква s), то оконная процедура получает два сообщения WM_CHAR подряд — первое с wParam равным коду ASCII самого диакритического знака (такое же значение wParam, как было передано с сообщением WM_DEADCHAR) и второе wParam равным коду ASCII буквы s.