лекции / Shchupak_Yu._Win32_API_Razrabotka_prilozheniy_dlya_Windows
.pdf
Программа «Hello, World!» — первый вариант |
41 |
|
|
|
|
typedef |
struct tagPoint { |
|
LONG |
x; |
|
LONG |
y; |
|
} POINT; |
|
|
Извлечение очередного сообщения осуществляется с помощью функции GetMessage, имеющей прототип:
BOOL GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax)
Параметр lpMsg задает адрес структуры типа MSG, в которую помещается выб ранное сообщение.
Параметр hWnd содержит дескриптор окна, принимающего сообщение. Обыч но значение этого параметра равно NULL, что позволяет выбрать сообщения для любого окна приложения.
Параметр wMsgFilterMin указывает минимальный номер принимаемого сообще ния. Обычно он имеет нулевое значение.
Параметр wMsgFilterMax задает максимальный номер принимаемого сообщения и тоже обычно имеет нулевое значение. Если оба последних параметра равны нулю, то функция выбирает из очереди любое очередное сообщение.
Функция GetMessage возвращает значение TRUE при извлечении любого сооб щения, кроме одного — WM_QUIT. Получив сообщение WM_QUIT, функция возвра щает значение FALSE. В результате этого происходит немедленный выход из цик ла, и приложение завершает работу, возвращая операционной системе код возврата msg.wParam.
Но какова дальнейшая судьба принятого сообщения?
В теле цикла обработки сообщений можно увидеть вызов двух функций:
TranslateMessage и DispatchMessage.
Строго говоря, вызов TranslateMessage нужен только в тех приложениях, ко торые должны обрабатывать ввод данных с клавиатуры. Дело в том, что для обес печения независимости от аппаратных платформ и различных национальных раскладок клавиатуры в Windows реализована двухуровневая схема обработки сообщений от символьных клавиш. Сначала система генерирует сообщения о так называемых виртуальных клавишах, например: сообщение WM_KEYDOWN — когда клавиша нажимается, и сообщение WM_KEYUP — когда клавиша отпускает ся. В сообщении WM_KEYDOWN содержится также информация о так называемом скан коде1 нажатой клавиши.
Функция TranslateMessageпреобразует пару сообщений, WM_KEYDOWNи WM_KEYUP, в сообщение WM_CHAR, которое содержит код символа (wParam) в виде значения типа TCHAR2. Сообщение WM_CHAR помещается в очередь, а на следующей итера ции цикла функция GetMessage извлекает его для последующей обработки.
Наконец, функция DispatchMessage передает структуру msg обратно в Windows. Очередной ход — за Windows. Windows отправляет сообщение для его обработ ки соответствующей оконной процедуре, вызывая ее как функцию обратного вызова.
1 Код, идентифицирующий нажатую клавишу и зависящий от аппаратной платформы.
2Тип TCHAR интерпретируется как char, если макрос UNICODE не определен. В ином случае он ин терпретируется как wchar_t (Unicode символ).
42 Глава 1. «Hello, World!», или Первые шаги к пониманию концепции Windows
Следует обратить внимание на то, что сообщение передается оконной проце дуре именно того окна, которому оно было адресовано. Это может быть или WndProc (если сообщение адресовано главному окну), или оконная процедура некоторого диалогового окна, или оконная процедура одного из стандартных элементов уп равления, спрятанная в недрах Windows (то есть в DLL).
После возврата из оконной процедуры Windows передает управление опера тору, указанному за вызовом DispatchMessage, то есть на начало цикла while, и ра бота цикла продолжается.
Как уже говорилось ранее, цикл обработки сообщений функционирует до тех пор, пока из очереди не поступит сообщение WM_QUIT. Появление этого сообще ния вызывает немедленный выход из цикла и прекращение работы программы.
Оконная процедура
Реальная работа приложения осуществляется в оконной процедуре (window procedure). Оконная процедура определяет то, что выводится в клиентскую об ласть окна, и то, как окну реагировать на пользовательский ввод.
Заголовок оконной функции всегда имеет следующий вид:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
Четыре параметра оконной процедуры идентичны первым четырем полям структуры MSG. Первый параметр функции содержит дескриптор окна, получаю щего сообщение. Во втором параметре указывается идентификатор сообщения. Для системных сообщений в Win32 зарезервированы номера от 0 до 1024. Третий и четвертый параметры содержат дополнительную информацию, которая распоз нается системой в зависимости от типа полученного сообщения.
Вместо имени WndProc можно использовать любое другое имя, но оно должно совпадать со значением поля lpfnWndProc структуры wc.
В рассматриваемой программе имеется только одно окно класса MyClass. Деск риптор окна hMainWnd получен вызовом функции CreateWindow. Поэтому при вы зове оконной процедуры ее параметру hWnd всегда передается значение hMainWnd. Если же в программе создается несколько окон на основе одного и того же класса окна (и, следовательно, имеющих одну и ту же оконную процедуру), тогда пара метру hWnd будет передаваться дескриптор конкретного окна, получающего сооб щение.
Обычно программисты используют оператор switch для определения того, ка кое сообщение получено и как его обрабатывать. Если сообщение обрабатыва ется, то оконная процедура обязана вернуть нулевое значение. Все сообщения, не обрабатываемые оконной процедурой, должны передаваться системной функции DefWindowProc. В этом случае оконная процедура должна вернуть то значение, которое возвращает DefWindowProc.
Таким образом, программист пишет код только для тех сообщений, которые нуждаются в нестандартной обработке. В программе Hello1 таких сообщений все го три: WM_PAINT, WM_CLOSE и WM_DESTROY.
Обработка сообщения WM_PAINT
Обработка сообщения WM_PAINT крайне важна для программирования под Win dows. Это сообщение уведомляет программу, что часть или вся клиентская область
Программа «Hello, World!» — первый вариант |
43 |
|
|
окна недействительна (invalid) и ее следует перерисовать. Во второй главе тема обработки сообщения WM_PAINT будет рассмотрена более подробно, поэтому здесь излагается тот минимум, который необходим для понимания работы программы
Hello1.
В каких ситуациях клиентская область окна становится недействительной? Очевидно, что при создании окна недействительна вся его клиентская область, поскольку в ней еще ничего не нарисовано. Это раз.
Если вы меняете размеры окна, клиентская область также объявляется сис темой недействительной, что обусловлено комбинацией стилей CS_HREDRAW | CS_VREDRAW в поле style структуры класса окна. Это два.
Когда вы минимизируете окно программы Hello1, сворачивая его на панель за дач, а затем снова разворачиваете до начального размера, то Windows объявляет клиентскую область окна недействительной. Это три.
Если вы перемещаете окна так, что они перекрываются, а затем закрытая часть окна вновь открывается, то Windows помечает требующую восстановления кли ентскую область как недействительную. Это четыре.
Можно было бы продолжить, но оставим подробности для второй главы.
Во всех перечисленных случаях, кроме первого, операционная система авто матически помечает клиентскую область окна как недействительную, что влечет за собой посылку сообщения WM_PAINT. В первом случае, когда окно только что было создано, аналогичный эффект достигается вызовом функции ShowWindow. В процессе ее выполнения генерируются сообщения WM_SIZE и WM_MOVE, а обра батывая WM_SIZE, система автоматически генерирует сообщение WM_PAINT.
Завершив этот маленький теоретический экскурс, вернемся к анализу нашего кода.
Обработку сообщения WM_PAINT рекомендуется всегда начинать с вызова функ ции BeginPaint:
hDC = BeginPaint(hWnd, &ps);
Первый параметр функции содержит дескриптор окна, полученный через ар гумент оконной процедуры, а второй — адрес структуры ps типа PAINTSTRUCT. Поля этой структуры, заполняемые в результате выполнения функции BeginPaint, в даль нейшем используются операционной системой1. Для нас сейчас более важно воз вращаемое функцией значение — это дескриптор так называемого контекста уст ройства.
Контекст устройства (device context) описывает физическое устройство выво да информации, например дисплей или принтер. Этот важнейший объект графи ческой подсистемы Windows рассматривается подробно во второй главе. Сейчас достаточно понимания того, что контекст устройства — это некоторая внутренняя структура данных, сохраняющая часто используемые графические атрибуты, такие как цвет фона, перо, кисть, шрифт и им подобные параметры. Эти атрибуты ис пользуются при вызове всех рисующих функций, получающих дескриптор hDC в качестве параметра.
Прежде чем перейти к следующей строке программного текста, отметим два побочных эффекта выполнения функции BeginPaint.
1 Более подробно структура PAINTSTRUCT рассматривается в главе 2.
44 Глава 1. «Hello, World!», или Первые шаги к пониманию концепции Windows
Во первых, обрабатывая вызов BeginPaint, система Windows обновляет фон клиентской области, если обновляемый регион помечен для стирания1. По умол чанию для этого используется кисть, заданная в поле hbrBackground структуры
WNDCLASSEX.
Во вторых, вызов функции BeginPaint делает всю клиентскую область действи тельной (valid), то есть не требующей перерисовки. Это предотвращает повтор ную генерацию системой сообщения WM_PAINT до тех пор, пока вновь не произой дет одно из событий, требующих перерисовки окна.
После вызова BeginPaint в рассматриваемой программе следует вызов функ ции GetClientRect, предназначенной для получения размеров клиентской области окна:
GetClientRect(hWnd, &rect);
Результат работы функции помещается в переменную rect типа RECT. Структу ра RECT, описывающая прямоугольник (rectangle), определена в заголовочных фай лах Windows следующим образом:
typedef struct tagRECT { LONG left;
LONG top; LONG right; LONG bottom;
} RECT;
Поля этой структуры задают координаты левого верхнего угла (left, top) и пра вого нижнего угла (right, bottom) прямоугольника.
После выполнения функции GetClientRect поля left и top всегда получают нуле вое значение, а поля right и bottom содержат ширину и высоту клиентской области в пикселах. Информация о размерах клиентской области, сохраненная в перемен ной rect, используется далее в «рисующей» функции DrawText.
В нашей программе все «рисование» сводится к выводу текста «Hello, World!» при помощи функции DrawText, имеющей следующий прототип:
BOOL DrawText( |
|
HDC hdc, |
// дескриптор контекста устройства |
LPCTSTR lpString, |
// указатель на символьную строку |
int nCount, |
// длина текста |
LPRECT lpRect, |
// указатель на ограничивающий прямоугольник |
UINT uFormat |
// флаги форматирования текста |
); |
|
Функция2 выводит текст из строки lpString в прямоугольную область, заданную структурой типа RECT, используя метод форматирования, заданный параметром uFormat. Количество символов в выводимой строке задается параметром nCount. Если установить значение nCount в –1, то система сама определит длину строки lpString по завершающему нулевому символу. Но в этом случае программист должен поза ботиться о том, чтобы строка действительно завершалась нулевым байтом.
На месте последнего параметра функции задан набор флагов DT_SINGLELINE | DT_CENTER | DT_VCENTER, значения которых определяются в заголовочных файлах
1 Информация об этом факте хранится в одном из полей структуры ps.
2Здесь приводятся минимальные сведения о работе функции DrawText. Подробно эта функция разби рается в главе 2.
Программа «Hello, World!» — первый вариант |
45 |
|
|
Windows. Флаги показывают, что текст будет выводиться в одну строку, по цент ру относительно горизонтали и вертикали внутри прямоугольной области, задан ной четвертым параметром. Благодаря этому текст «Hello, World!» выводится в центре клиентской области.
Когда клиентская область становится недействительной (например, при из менении размеров окна), WndProc получает новое сообщение WM_PAINT. Обраба тывая его, программа вновь вызывает функцию GetClientRect и поэтому рисует текст опять в центре окна.
После окончания работы с графическими функциями в блоке обработки сооб щения WM_PAINT необходимо освободить полученный контекст устройства с по мощью функции EndPaint.
Следует отметить, что при выводе текста используются текущие установки для шрифта, цвета фона и цвета текста. О том, как управлять этими атрибутами, будет рассказано во второй главе. Для тех, кто хочет экспериментировать с цветами тек ста и фона немедленно, ниже приводится краткая справка.
Атрибуты цвета и фона для выводимого текста
В приложении может использоваться функция SetTextColor для установки цвета текста (text color) в клиентской области окна. Функция SetBkColor используется для установки цвета фона графического элемента (background color), то есть цве та, который отображается позади каждого символа. Еще можно регулировать ре жим смешивания фона (background mix mode), вызывая функцию SetBkMode. Ее вто рой параметр может принимать значение OPAQUE1, если цвет фона графического элемента выводится поверх существующего фона окна, прежде чем будет выве ден символ. Также можно использовать значение TRANSPARENT2, при котором цвет фона графического элемента игнорируется, а символ выводится на существую щем фоне.
Если эти функции не вызывались, то в контексте устройства будут использо ваны значения по умолчанию, приведенные в табл. 1.11.
Таблица 1.11. Атрибуты цвета и фона текста по умолчанию
Атрибут |
Значение по умолчанию |
|
|
Цвет текста |
Черный |
Цвет фона графического элемента |
Белый |
Режим смешивания фона |
OPAQUE |
|
|
Именно эти параметры и использовались при работе программы Hello1.
Обработка сообщений WM_CLOSE и WM_DESTROY
Сообщение WM_CLOSE появляется, когда пользователь щелкает мышью на кнопке закрытия окна или нажимает комбинацию клавиш Alt+F4. Вообще, обработка это го сообщения не обязательна: если она отсутствует, то функция DefWindowProc вы зовет по умолчанию функцию DestroyWindow. Но если вы хотите предусмотреть вывод каких либо предупреждающих сообщений типа «А вы точно уверены, что
1 Непрозрачный режим смешивания фона.
2 Прозрачный режим смешивания фона.
46 Глава 1. «Hello, World!», или Первые шаги к пониманию концепции Windows
хотите это сделать?», то данное место — самое подходящее. Ибо окно еще не раз рушено, а вот после сообщения WM_DESTROY окна на экране уже нет.
Функция DestroyWindow, оправдывая свое имя, разрушает указанное в ее пара метре окно. Для этого она посылает окну сообщение WM_DESTROY. Если у данного окна есть дочерние окна, то функция посылает WM_DESTROY сначала ему, а потом уже дочерним окнам. Функция завершает свою работу только после уничтоже ния всех дочерних окон.
Когда главное окно приложения получает сообщение WM_DESTROY, то оконная процедура должна позаботиться о том, чтобы приложение корректно «покинуло сцену». Для этого вызывается функция PostQuitMessage, посылающая сообщение WM_QUIT. Ну а что происходит в цикле обработки сообщений при появлении WM_QUIT, вы уже знаете.
Разрешите вас поздравить: мы завершили анализ текста программы Hello1 — первого варианта приложения «Hello, World!».
Как, будет еще и второй вариант?.. — Не волнуйтесь, пояснения к нему будут гораздо короче.
Программа «Hello, World!» — второй вариант
Программу «Hello, World!» часто используют как каркас нового Windows прило жения. Иными словами, начало работы над новой программой обычно происхо дит по такому сценарию: вы создаете новый проект, открываете новый пустой файл для функции WinMain, копируете в него содержимое файла Hello1.cpp1, а потом вно сите необходимые изменения и дополнения.
Но такой способ работы, мне кажется, должен оскорблять чувства программи ста, пишущего на C++. Почему бы не воспользоваться известными средствами языка, позволяющими реализовать повторное использование кода гораздо более изящным способом? Вы уже догадались, что речь идет о программировании с клас сами? — Да, конечно.
Здесь предлагается одна из возможных реализаций этой идеи. Класс KWnd, пред ставленный ниже, инкапсулирует код, отвечающий за регистрацию оконного класса, создание окна и показ его на экране.
Соблюдая традицию [9], будем размещать код для каждого нового класса в двух файлах: интерфейс — в файле с расширением .h, а реализацию — в файле с расширением .cpp. Таким образом, программа реализуется как многофайловый проект, приведенный в листинге 1.22.
Листинг 1.2. Проект Hello2
//////////////////////////////////////////////////////////////////////
// KWnd.h
#include <windows.h> class KWnd {
1 Не писать же все заново!
2 Если у вас есть вопросы по созданию многофайловых проектов, то обратитесь к приложению 1.
Программа «Hello, World!» — второй вариант |
47 |
|
|
public:
KWnd(LPCTSTR windowName, HINSTANCE hInst, int cmdShow, LRESULT (WINAPI *pWndProc)(HWND,UINT,WPARAM,LPARAM), LPCTSTR menuName = NULL,
int x = CW_USEDEFAULT, int y = 0,
int width = CW_USEDEFAULT, int height = 0, UINT classStyle = CS_HREDRAW | CS_VREDRAW, DWORD windowStyle = WS_OVERLAPPEDWINDOW, HWND hParent = NULL);
HWND GetHWnd() { return hWnd; } protected:
HWND hWnd; WNDCLASSEX wc;
};
//////////////////////////////////////////////////////////////////////
// KWnd.cpp #include "KWnd.h"
KWnd::KWnd(LPCTSTR windowName, HINSTANCE hInst, int cmdShow, LRESULT (WINAPI *pWndProc)(HWND,UINT,WPARAM,LPARAM),
LPCTSTR menuName, int x, int y, int width, int height, UINT classStyle, DWORD windowStyle, HWND hParent)
{
char szClassName[] = "KWndClass";
wc.cbSize |
= sizeof(wc); |
wc.style |
= classStyle; |
wc.lpfnWndProc |
= pWndProc; |
wc.cbClsExtra |
= 0; |
wc.cbWndExtra |
= 0; |
wc.hInstance |
= hInst; |
wc.hIcon |
= LoadIcon(NULL, IDI_APPLICATION); |
wc.hCursor |
= LoadCursor(NULL, IDC_ARROW); |
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); |
|
wc.lpszMenuName |
= menuName; |
wc.lpszClassName = szClassName; |
|
wc.hIconSm |
= LoadIcon(NULL, IDI_APPLICATION); |
// Регистрируем класс окна if (!RegisterClassEx(&wc)) {
char msg[100] = "Cannot register class: "; strcat(msg, szClassName);
MessageBox(NULL, msg, "Error", MB_OK); return;
} |
|
|
// Создаем окно |
|
|
hWnd = CreateWindow(szClassName, windowName, windowStyle, |
|
|
x, y, width, height, hParent, (HMENU)NULL, hInst, NULL); |
|
|
if (!hWnd) { |
|
|
char text[100] = "Cannot create window: "; |
|
|
strcat(text, windowName); |
|
|
MessageBox(NULL, text, "Error", MB_OK); |
|
|
return; |
продолжение |
|
|
48 Глава 1. «Hello, World!», или Первые шаги к пониманию концепции Windows
Листинг 1.2 (продолжение)
}
// Показываем окно ShowWindow(hWnd, cmdShow);
}
//////////////////////////////////////////////////////////////////////
// Hello2.cpp #include <windows.h> #include "KWnd.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //====================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
KWnd mainWnd("A Hello2 application", hInstance, nCmdShow, WndProc);
while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg);
}
return msg.wParam;
}
//==================================================================== LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HDC hDC; PAINTSTRUCT ps; RECT rect;
int userReply;
switch (uMsg)
{
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps);
GetClientRect(hWnd, &rect);
DrawText(hDC, "Hello, World!", -1, &rect,
DT_SINGLELINE | DT_CENTER | DT_VCENTER );
EndPaint(hWnd, &ps); break;
case WM_CLOSE:
userReply = MessageBox(hWnd, "А вы уверены в своем желании закрыть приложение?", "", MB_YESNO | MB_ICONQUESTION);
if (IDYES == userReply) DestroyWindow(hWnd);
break;
case WM_DESTROY: PostQuitMessage(0); break;
default:
Функции поддержки окон |
49 |
|
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
return 0;
}
//////////////////////////////////////////////////////////////////////
Обратите внимание на следующие моменты предложенного решения:
Заголовок конструктора класса KWnd содержит 12 параметров. Первые четы ре параметра являются обязательными, а остальные имеют значения по умол чанию.
Четвертый параметр является указателем на функцию, принимающую четыре аргумента и возвращающую значение типа LRESULT. Здесь обязателен специ фикатор WINAPI или эквивалентный ему спецификатор __stdcall.
Код, отвечающий за подготовку и создание окна, размещен в теле конструкто ра класса KWnd.
В теле функции WinMain определяется объект mainWnd класса KWnd, после чего остается только записать цикл обработки сообщений.
В оконной процедуре усложнена обработка сообщения WM_CLOSE по сравне нию с первой версией программы. При помощи функции MessageBox пользова телю предлагается подтвердить его желание закрыть приложение. Благодаря флагу MB_YESNO диалоговое окно будет содержать две кнопки: YES и NO. При щелчке мышью на кнопке YES функция возвратит значение IDYES, и только в этом случае будет вызвана функция DestroyWindow.
Откомпилируйте эту программу (проект Hello2), чтобы убедиться в ее рабо тоспособности. Поэкспериментируйте с передачей других значений аргументов конструктору объекта mainWnd. Например, замените строку
KWnd mainWnd("Hello application", hInstance, nCmdShow, WndProc);
на строку
KWnd mainWnd("Hello application", hInstance, nCmdShow, WndProc, NULL, 50, 100, 200, 150);
и посмотрите на поведение измененной программы.
Разработка второго варианта программы «Hello, World!» завершена. Реализо ванный в ней класс KWnd можно использовать для сокращения кода новых прило жений.
ВНИМАНИЕ
Если вы будете использовать класс KWnd, то подключите к вашему проекту файлы KWnd.h и KWnd.cpp, а также добавьте директиву #include "KWnd.h" в том файле, где он используется.
Функции поддержки окон
Win32 API предоставляет широкий набор функций, которые позволяют менять размеры, расположение и характеристики отображения окна. В табл. 1.12 приве дены наиболее употребительные функции.
50 Глава 1. «Hello, World!», или Первые шаги к пониманию концепции Windows
Таблица 1.12. Функции поддержки окон
Функция |
Назначение |
|
|
BringWindowToTop |
Активизирует окно и переносит его в верхнее положение, если оно |
|
находится позади других окон |
CloseWindow |
Сворачивает окно |
EnableWindow |
Разрешает или запрещает окну принимать ввод данных от мыши или |
|
клавиатуры |
FindWindow |
Находит окно верхнего уровня по заданным имени класса и имени |
|
îêíà |
GetActiveWindow |
Выбирает дескриптор активного окна |
GetClassInfo |
Извлекает информацию о классе окна в структуру типа WNDCLASS |
GetClassLong |
Выбирает специфицированное по индексу значение из структуры |
|
òèïà WNDCLASSEX |
GetClientRect |
Получает координаты клиентской области окна |
GetFocus |
Выбирает дескриптор окна, имеющего фокус ввода |
GetParent |
Выбирает дескриптор родительского окна |
GetWindow |
Выбирает дескриптор окна |
GetWindowInfo |
Извлекает информацию об окне в структуру типа WINDOWINFO |
GetWindowLong |
Выбирает указанное по индексу значение из данных окна |
GetWindowRect |
Получает координаты левого верхнего и правого нижнего углов окна |
IsChild |
Определяет, является ли окно дочерним по отношению к данному |
|
родительскому окну |
IsIconic |
Проверяет, свернуто ли окно |
IsZoomed |
Проверяет, развернуто ли окно |
IsWindowEnabled |
Проверяет, разрешено или запрещено окно |
MoveWindow |
Перемещает и изменяет размеры окна |
SetActiveWindow |
Делает окно активным |
SetClassLong |
Замещает указанным 32-битным значением прежнее значение ука- |
|
занного поля в структуре WNDCLASSEX для класса, к которому отно- |
|
сится указанное окно |
SetFocus |
Придает окну фокус ввода |
SetWindowLong |
Изменяет атрибуты указанного окна (первоначально заданные |
|
функцией CreateWindow) |
SetWindowPos |
Изменяет одновременно размеры, позицию и расположение окна |
|
относительно других окон |
SetWindowText |
Изменяет текст заголовка окна |
ShowWindow |
Отображает, скрывает или изменяет состояние показа окна |
UpdateWindow |
Обновляет клиентскую область окна при помощи посылки сообщения |
|
WM_PAINT непосредственно оконной процедуре, минуя очередь сооб- |
|
щений приложения |
|
|
Часто используемые сообщения
В табл. 1.13 приведены сообщения, обработка которых в оконной процедуре встре чается наиболее часто.
