Сообщения Windows обрабатываются оконной функцией. Типы сообщений представляются 32-разрядными словами. Для идентификации этих чисел применяются макроимена. Наиболее часто используются следующие макроимена сообщений:
WM_CHAR — нажата клавиша;
WM_PAINT — запрос на перерисовку окна;
WM_LBUTTONDOWN — нажата левая кнопка мыши;
WM_RBUTTONDOWN — нажата правая кнопка мыши;
WM_COMMAND — выбрана команда меню;
WM_TIMER — истечение заданного интервала времени.
Каждое сообщение имеет два 32-разрядных параметра типов WPARAM и LPARAM. Обработку сообщений выполняет оконная функция, имеющая четыре параметра: дескриптор окна, сообщение и два указанных выше параметра.
Для доступа к младшему и старшему словам 32-битного двойного слова применяются функции LOWORD и HIWORD. Например, операции
x = LOWORD(lParam);
y = HIWORD(lParam);
записывают в (x, y) координаты курсора мыши в случаях обработки сообщения о нажатии левой или правой кнопки мыши.
Обработка нажатия клавиши. Для сообщения WM_CHAR параметр wParam содержит ASCII – код нажатой клавиши, LOWORD(lParam) – количество повторов, генерируемых при удержании клавиши в нажатом состоянии, HIWORD(lParam) содержит следующую информацию, определенную значениями битов:
15: 1 – клавиша отпущена, 0 – нажата;
14: устанавливается, если клавиша уже была нажата перед посылкой сообщения;
13: дополнительно нажата клавиша [ALT];
12-9: используется системой;
8: нажата дополнительная или функциональная часть клавиатуры;
7-0: scan – код клавиши.
Для того, чтобы добавить в написанный выше каркас приложения обработку события WM_CHAR, определим массив символов для ввода и подключим библиотеки обработки строки и вывода на экран:
#include <string.h>
#include <stdio.h>
char str[80] = “ ”; // буфер для строки ввода
Добавив обработку события WM_CHAR, получаем следующую оконную функцию:
LRESULT CALLBACK WindowFunc(HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
HDC hdc;
switch(message)
{
case WM_CHAR:
hdc = GetDC(hwnd); // получить контекст устройства
TextOut(hdc, 1, 1, “ “, 2); // стереть старый символ
sprintf(str, “%c”, (char)wParam); // записать в буфер новый символ
TextOut(hdc, 1, 1, str, strlen(str)); // вывести на экран
ReleaseDC(hwnd, hdc); // освободить контекст устройства
break;
case WM_DESTROY:
PostQuitMessage(0); // сообщение о завершении
break;
default: // обработка остальных сообщений
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
Обработка запроса на перерисовку окна. Если нажать кнопку минимизации окна, а затем вновь распахнуть окно, то символы, записанные в окне с помощью TextOut(), будут потеряны. Система Windows, как правило, не запоминает содержимое окна, но каждый раз, когда нужно перерисовать окно, она посылает оконной функции сообщение WM_PAINT.
В некоторых случаях при перемещении и при изменении размеров окна система сохраняет и перерисовывает содержимое окна, но это не касается случая, когда окно минимизируется или перекрывается другим окном, а потом делается попытка восстановить его в исходное состояние. Для того, чтобы обрабатывать сообщение WM_PAINT, добавим соответствующий этому сообщению случай в оператор switch функции окна:
case WM_PAINT:
hdc = BeginPaint(hwnd, &paintstruct); // получить DC
TextOut(hdc, 1, 1, str, strlen(str));
EndPaint(hwnd, &paintstruct); // освободить DC
break;
В данном случае применяются другие функции получения и освобождения контекста устройства. Они имеют дополнительный параметр, равный адресу структуры.
struct PAINTSTRUCT
{
HDC hdc; // дескриптор DC
BOOL fErase; // true, если перерисовывается заполнение окна
RECT rcPaint; // координаты области перерисовки
BOOL fRestore, fIncUpdate; // резерв
BYTE rgbReserved[32]; // резерв
}
Здесь тип RECT описывает структуру
struct RECT
{
LONG left, top, right, bottom;
}
Для обработки сообщения WM_PAINT добавим определение