Оконные приложения строятся по принципам событийно-управляемого программирования (event-driven programming) — стиля программирования, при котором поведение компонента системы определяется набором возможных внешних событий и ответных реакций компонента на них. Такими компонентами в Windows являются окна.
С каждым окном в Windows связана определенная функция обработки событий – оконная функция. События для окон называются сообщениями. Сообщение относится к тому или иному типу, идентифицируемому определенным кодом (32-битным целым числом), и сопровождается парой 32-битных параметров (WPARAM и LPARAM), интерпретация которых зависит от типа сообщения.
Задача любого оконного приложения — создать главное окно и сообщить Windows функцию обработки событий для этого окна. Все самое интересное для приложения будет происходить именно в функции обработки событий главного окна.
В Windows программа пассивна. После запуска она ждет, когда ей уделит внимание операционная система. Операционная система делает это посылкой сообщений. Сообщения могут быть разного типа, они функционируют в системе достаточно хаотично, и приложение не знает, какого типа сообщение придет следующим. Логика построения Windows-приложения должна обеспечивать корректную и предсказуемую работу при поступлении сообщений любого типа.
Классическое оконное приложение, как правило, состоит по крайней мере из двух функций:
Стартовая функция WinMain
В консольной программе на С точкой входа является функция main(). С этого места программа начинает выполняться. Точкой входа программы для Windows является функция WinMain().
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR szCmdLine,
int iCmdShow) {…}
Эта функция использует последовательность вызовов API и при завершении возвращает операционной системе целое число.
Аргументы функции:- hInstance – дескриптор процесса (instance handle) – число, идентифицирующее программу, когда она работает под Windows. Если одновременно работают несколько копий одной программы, каждая копия имеет свое значение hInstance.
- hPrevInstance — предыдущий дескриптор процесса (previous instance) — в настоящее время устарел, всегда равен NULL.
- szCmdLine — указатель на оканчивающуюся нулем строку, в которой содержатся параметры, переданные в программу из командной строки. Можно запустить программу с параметром командной строки, вставив этот параметр после имени программы в командной строке.
- iCmdShow — целое константное значение, показывающее, каким должно быть выведено на экран окно в начальный момент. Задается при запуске программы другой программой. В большинстве случаев число равно 1 (SW_SHOWNRMAL).
Имя | Значение | Описание |
SW_HIDE | 0 | Скрывает окно и делает активным другое окно |
SW_SHOWNORMAL | 1 | Отображает и делает активным окно в его первоначальном размере и положении. |
SW_SHOWMINIMIZED | 2 | Активизирует окно и отображает его в свернутом виде |
SW_SHOWMAXIMIZED | 3 | Активизирует окно и отображает его в полноэкранном виде |
SW_SHOWNOACTIVATE | 4 | Отображает окно аналогично SW_SHOWNORMAL, но не активизирует его |
SW_SHOW | 5 | Отображает и делает активным окно с текущим размером и положением. |
SW_MINIMIZE | 6 | Сворачивает текущее окно и делает активным следующее окно в порядке очереди. |
SW_SHOWMINNOACTIVE | 7 | Сворачивает окно аналогично SW_SHOWMINIMIZED, но не активизирует его. |
SW_SHOWNA | 8 | Отображает окно в текущей позиции аналогично SW_SHOW, но не активизирует его. |
SW_RESTORE | 9 | Отображает и активизирует окно. Если окно было свернуто или развернуто во весь экран, оно отображается в своем первоначальном положении и размере. |
SW_SHOWDEFAULT | 10 | Отображает окно способом, заданным по умолчанию. |
SW_FORCEMINIMIZE | 11 | Применяется для минимизации окон, связанных с различными потоками. |
В структуре стартовой функции Windows можно выделить следующие операции, образующие «скелет» программы:
Регистрация класса окна
Регистрация класса окна осуществляется функцией
Прототип функции находится в файле библиотеки user32.dll. Единственным аргументом функции является указатель на структуру
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HINSTANCE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName; } WNDCLASS;
Члены структуры style — устанавливает стиль(и) класса. Этот член структуры может быть любой комбинацией стилей класса.
Имя | Значение | Описание |
CS_VREDRAW | 0x01 | Вертикальная перерисовка: осуществлять перерисовку окна при перемещении или изменении высоты окна. |
CS_HREDRAW | 0x02 | Горизонтальная перерисовка: осуществлять перерисовку окна при перемещении или изменении ширины окна. |
CS_KEYCVTWINDOW | 0x04 | В окне будет выполняться преобразование виртуальных клавиш. |
CS_DBLCLKS | 0x08 | Окну будут посылаться сообщения о двойном щелчке кнопки мыши. |
CS_OWNDC | 0x20 | Каждому экземпляру окна присваивается собственный контекст изображения. |
CS_CLASSDC | 0x40 | Классу окна присваивается собственный контекст изображения, который можно разделить между копиями. |
CS_PARENTDC | 0x80 | Классу окна передается контекст изображения родительского окна. |
CS_NOKEYCVT | 0x100 | Отключается преобразование виртуальных клавиш. |
CS_NOCLOSE | 0x200 | Не закрываемое окно: в системном меню блокируется выбор пункта закрытия окна. |
CS_SAVEBITS | 0x800 | Часть изображения на экране, закрытая окном, сохраняется. |
CS_BYTEALIGNCLIENT | 0x1000 | Выравнивание клиентской области окна: использование границы по байту по оси x. |
CS_BYTEALIGNWINDOW | 0x2000 | Выравнивание окна: bспользование границы по байту по оси x. |
CS_PUBLICCLASS CS_GLOBALCLASS | 0x4000 | Определяется глобальный класс окон. |
lpfnWndProc — указатель на оконную процедуру.
cbClsExtra — устанавливает число дополнительных байт, которые размещаются вслед за структурой класса окна. Система инициализирует эти байты нулями, в большинстве случаев равен 0.
cbWndExtra— устанавливает число дополнительных байтов, которые размещаются вслед за экземпляром окна. Система инициализирует байты нулями.
hInstance — дескриптор экземпляра, который содержит оконную процедуру для класса.
hIcon — дескриптор значка класса, дескриптор ресурса значка. Если этот член структуры — NULL, система предоставляет заданный по умолчанию значок.
hCursor — дескриптор курсора класса, дескриптор ресурса курсора. Если этот член структуры — NULL, приложение устанавливает форму курсора всякий раз, когда мышь перемещается в окно прикладной программы.
hbrBackground — дескриптор кисти фона класса, дескриптор физической кисти, которая используется, чтобы красить цветом фона, или код цвета, преобразованный к типу HBRUSH.
lpszMenuName — указатель на символьную строку с символом конца строки ('\0'), которая устанавливает имя ресурса меню класса. Можно использовать целое число, чтобы идентифицировать меню с помощью макроса MAKEINTRESOURCE(int). Если этот член структуры — NULL, окна, принадлежащие этому классу, не имеют заданного по умолчанию меню.
lpszClassName — указатель на символьную строку с именем класса, оканчивающуюся '\0'.
Создание окна
Создание окна осуществляется функцией
_In_opt_ LPCTSTR lpClassName,
_In_opt_ LPCTSTR lpWindowName,
_In_ DWORD dwStyle,
_In_ int x,
_In_ int y,
_In_ int nWidth,
_In_ int nHeight,
_In_opt_ HWND hWndParent,
_In_opt_ HMENU hMenu,
_In_opt_ HINSTANCE hInstance,
_In_opt_ LPVOID lpParam );
Прототип функции находится в файле библиотеки user32.dll. Возвращаемое значение – дескриптор создаваемого окна. В случае невозможности создать окно возвращается NULL.
Аргументы функции:
lpClassName – указывает на строку с ‘\0’ в конце, которая определяет имя класса окна. Имя класса может быть зарегистрированным функцией RegisterClass или любым из предопределенных имен класса элементов управления.lpWindowName — указывает на строку с ‘\0’ в конце, которая определяет имя окна.
dwStyle — определяет стиль создаваемого окна.
Имя | Значение | Описание |
WS_BORDER | 0x00800000 | Окно имеет тонкую границу в виде линии. |
WS_CAPTION | 0x00C00000 | Окно имеет строку заголовка. |
WS_CHILD | 0x40000000 | Окно является дочерним. |
WS_DISABLED | 0x08000000 | Окно является изначально неактивным. |
WS_GROUP | 0x00020000 | Окно группирует другие управляющие элементы. |
WS_HSCROLL | 0x00100000 | Окно содержит горизонтальную полосу прокрутки. |
WS_MAXIMIZE | 0x01000000 | Исходный размер окна – во весь экран. |
WS_MINIMIZE | 0x20000000 | Исходно окно свернуто. |
WS_OVERLAPPED | 0x00000000 | Окно может быть перекрыто другими окнами. |
WS_POPUP | 0x80000000 | Всплывающее окно. |
WS_SYSMENU | 0x00080000 | Окно имеет системное меню в строке заголовка. |
WS_VISIBLE | 0x10000000 | Окно изначально видимое. |
WS_VSCROLL | 0x00200000 | Окно имеет вертикальную полосу прокрутки. |
x — определяет координату левой стороны окна относительно левой стороны экрана. Измеряется в единицах измерения устройства, чаще всего в точках (pt). Для дочернего окна определяет координату левой стороны относительно начальной координаты родительского окна. Если установлен как CW_USEDEFAULT, Windows выбирает заданную по умолчанию позицию окна.
у – определяет координату верхней стороны окна относительно верхней стороны экрана. Измеряется в единицах измерения устройства, чаще всего в точках (pt). Для дочернего окна определяет координату верхней стороны относительно начальной координаты родительского окна.
nWidth – определяет ширину окна в единицах измерения устройства. Если параметр соответствует CW_USEDEFAULT, Windows выбирает заданную по умолчанию ширину и высоту для окна.
nHeight – определяет высоту окна в единицах измерения устройства.
hWndParent – дескриптор родительского окна.
hMenu – идентифицирует меню, которое будет использоваться окном. Этот параметр может быть NULL, если меню класса будет использовано.
hInstance — идентифицирует экземпляр модуля, который будет связан с окном.
lpParam — указывает на значение, переданное окну при создании.
Отображение и перерисовка окна
Отображение окна осуществляется функцией
_In_ HWND hWnd,
_In_ int nCmdShow);
Прототип функции находится в файле библиотеки user32.dll. Возвращаемое значение: 1 – успешное отображение окна, 0 – ошибка.
Аргументы функции:
hWnd – дескриптор отображаемого окна.
nCmdShow – константа, определяющая, как будет отображаться окно согласно таблице.
Перерисовка окна осуществляется функцией
Прототип функции находится в файле библиотеки user32.dll. Возвращаемое значение: 1 – успешная перерисовка окна, 0 – ошибка. Аргумент функции hWnd – дескриптор окна.
Цикл обработки сообщений
После вызова функции UpdateWindow, окно окончательно выведено на экран. Теперь программа должна подготовить себя для получения информации от пользователя через клавиатуру и мышь.
Windows поддерживает «очередь сообщений» (message queue) для каждой программы, работающей в данный момент в системе Windows.
Когда происходит ввод информации, Windows преобразует ее в «сообщение», которое помещается в очередь сообщений программы.
Программа извлекает сообщения из очереди сообщений, выполняя блок команд, известный как «цикл обработки сообщений» (message loop):
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Для получения сообщения из очереди используется функция:
_Out_ LPMSG lpMsg,
_In_opt_ HWND hWnd,
_In_ UINT wMsgFilterMin,
_In_ UINT wMsgFilterMax);
Прототип функции находится в файле библиотеки user32.dll. В случае получения из очереди сообщения, отличного от WM_QUIT, возвращает ненулевое значение.
Аргументы функции:
lpMsg — указатель на структуру сообщения.
{
HWND hwnd; // дескриптор окна, очередь сообщений которого просматривается
UINT message; // идентификатор сообщения
WPARAM wParam; // дополнительная информация о сообщении,
LPARAM lParam; // зависит от идентификатора сообщения
DWORD time; // время помещения сообщения в очередь
POINT pt; // структура, содержащая координаты курсора в момент помещения сообщения в очередь
} MSG;
Структура POINT имеет вид
{
LONG x; // координата x
LONG y; // координата y
} POINT;
hWnd — дескриптор окна, очередь для которого просматривается.
wMsgFilterMin — нижняя граница фильтра идентификаторов сообщений.
wMsgFilterMax — верхняя граница фильтра идентификаторов сообщений.
Функция
передает аргумент — структуру msg обратно в Windows для преобразования какого-либо сообщения с клавиатуры. Возвращает ненулевое значение в случае успешной расшифровки сообщения, 0 – ошибка.
Функция
передает аргумент — структуру msg обратно в Windows. Windows отправляет сообщение для его обработки соответствующей оконной процедуре — таким образом, Windows вызывает соответствующую оконную функцию, указанную при регистрации класса окна.
После того, как оконная функция обработает сообщение, оно возвращается в Windows, которая все еще обслуживает вызов функции DispatchMessage. Когда Windows возвращает управление в стартовую функцию WinMain() к следующему за вызовом DispatchMessage коду, цикл обработки сообщений в очередной раз возобновляет работу, вызывая GetMessage. Возвращает значение, определяемое оконной функцией, которое чаще всего игнорируется. Прототипы функций находятся в файле библиотеки user32.dll.
Пример стартовой функции, создающей и выводящей окно размером 500х300 точек:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <windows.h>
#include <tchar.h>
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
HWND hwnd; // дескриптор окна
MSG msg; // структура сообщения
WNDCLASS w; // структура класса окна
// Регистрация класса окна
memset(&w, 0, sizeof(WNDCLASS));
w.style = CS_HREDRAW | CS_VREDRAW;
w.lpfnWndProc = WndProc; // имя оконной функции
w.hInstance = hInstance;
w.hbrBackground = (HBRUSH)(WHITE_BRUSH);
w.lpszClassName = _T("My Class");
RegisterClass(&w);
// Создание окна
hwnd = CreateWindow(_T("My Class"), _T("Окно пользователя"),
WS_OVERLAPPEDWINDOW, 500, 300, 500, 380, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nCmdShow); // отображение
UpdateWindow(hwnd); // перерисовка
// Цикл обработки сообщений
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
Примечание: Для корректной сборки приложения используется многобайтовая кодировка.
Оконная функция - обработка сообщений окна
Оконная функция предназначена для обработки сообщений окна. Функция обработки сообщений окна организована по принципу ветвления, состоящего из последовательной проверки типа сообщения. При совпадении типа сообщения, переданного в структуре Message с соответствующей веткой, осуществляется его обработка. Минимальный вид оконной функции представлен ниже.
2
3
4
5
6
7
8
9
10
11
12
{
switch (Message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, Message, wparam, lparam);
}
return 0;
}
4 аргумента оконной функции идентичны первым четырем полям структуры сообщения MSG.
В примере обрабатывается только один тип сообщения WM_DESTROY, которое передается оконной функции при закрытии окна.
Вызов функции DefWindowProc() обрабатывает по умолчанию все сообщения, которые не обрабатывает оконная процедура.
Функция PostQuitMessage() сообщает Windows, что данный поток запрашивает завершение. Аргументом является целочисленное значение, которое функция вернет операционной системе.
Результат выполнения программы, выводящей окно:
В этих строчках происходит объявление переменных?
HWND hwnd; // дескриптор окнаMSG msg; // структура сообщения
Такие типы переменных используются в языках C и C++?
Стандартных таких типов данных, конечно же, нет. Но они определены в файле windows.h и используются в API-функциях в качестве аргументов (и возвращаемых значений).
О переопределении типов подробнее можете узнать здесь.
Подскажите, пожалуйста, на каком языке написано приведённое в Вашей статье оконное приложение на Си или C++? На нескольких форумах спрашивал, везде отвечают по разному. Очень хочется понять по каким признакам в этом исходном коде определить язык программирования.
На самом деле язык Си от C++ отличить достаточно сложно. Дело в том, что C++ расширяет функционал языка Си, а не замещает его. То есть все конструкции Си доступны в C++ в неизменном виде.
В данном случае я бы отнесла этот код к языку Си.
Спасибо! Хочу сказать, что Ваш сайт очень полезен.
Здравствуйте. Скажите пожалуйста, почему переменная <span class = 'prog'><span class=blu'>HWND</span> hwnd</span> объявлена дважды: один раз в начале функции <span class='prog'>WinMain</span> —
2
{ HWND hwnd; // дескриптор окна
и второй раз в функции WndProc —
Спасибо!
Переменная hwnd объявлена только в первом случае.
В функции WndProc она является аргументом, переданным из WinMain
И ещё один вопрос, если можно, правильно ли я понимаю, что исходный код ниже состоит из C++ и набора функций WinApi (MessageBox, GetDlgItemInt, CreateWindowEx) ?
Оконное Win32 приложение в Visual Studio, складывает два числа:…
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
void Addition(HWND hWnd) {
BOOL success = false;
int a = GetDlgItemInt(hWnd, EDIT1, &success, true);
if (!success) {
MessageBox(hWnd, TEXT("В первом поле не целое число"), TEXT("Ошибка"), MB_OK);
}
int b = GetDlgItemInt(hWnd, EDIT2, &success, true);
if (!success) {
MessageBox(hWnd, TEXT("Во втором поле не целое число"), TEXT("Ошибка"), MB_OK);
}
int c = a + b;
SetDlgItemInt(hWnd, EDIT3, c, true);
}
//Оконная функция
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_CREATE: //Первое число
CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT("0"), WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_TABSTOP,
20, 10, 85, 25, hWnd, HMENU(EDIT1), GetModuleHandle(NULL), NULL);
//Второе число
CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT("0"), WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_TABSTOP,
20, 45, 85, 25, hWnd, HMENU(EDIT2), GetModuleHandle(NULL), NULL);
//Сюда будем выводить результат
CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT("0"), WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_TABSTOP,
20, 85, 85, 25, hWnd, HMENU(EDIT3), GetModuleHandle(NULL), NULL);
//Кнопка сложения
CreateWindowEx(NULL, TEXT("BUTTON"), TEXT("+"), WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP,
115, 45, 30, 25, hWnd, HMENU(BUTTON), GetModuleHandle(NULL), NULL);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case BUTTON:
Addition(hWnd);
return 1;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Или здесь только чистый C++
Приведенный код состоит из ВЫЗОВА API-функции с помощью конструкций языка C++. Тело API функций содержится в системных библиотеках, а мы в своей программе только обращаемся к ним, чтобы они выполнили требуемые действия. Но мы не переопределяем работу API-функций.
Скажите, пожалуйста, можно ли код обработки сообщения в теле функции WndProc написать на языке С++ или используются только функции WinApi?
2
3
4
5
6
7
8
{
case WM_…: //сообщение
//здесь не понятно как пишется код обработки сообщения на C++ или C++ тут вообще не используется
case WM_…:
//обрабатываем
case WM_…:
//обрабатываем
Если можно применить С++, то чем отличается набор кода С++ в оконном приложении от набора в консольном, есть какие-то нюансы?
На самом деле Вы сами пишете код обработки на C++, и этот код вызывает API-функции.
Вы можете использовать те действия, которые считаете нужным, никаких нюансов тут нет.
Что касается отличия от консольных приложений, то тут имеет место то, какие API-функции могут быть вызваны в том и другом случае.
Здравствуйте! Помогите пожалуйста немного дополнить программу на C++ Программа выводит пустое Windows окно, а нужно чтобы в этом окне появилась геометрическая фигура (квадрат). Вот исходник:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
набор функций для отображения окна.
Эта программа станет базовой заготовкой для всех последующих программ*/
#include <windows.h>
//Создаём прототип функции окна
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//объявляем имя программы
char szProgName[]=&qout;Имя программы&qout;;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
HWND hWnd; //идентификатор окна
MSG lpMsg;
WNDCLASS w; //создаём экземпляр структуры WNDCLASS и начинаем её заполнять
w.lpszClassName=szProgName; //имя программы
w.hInstance=hInstance; //идентификатор текущего приложения
w.lpfnWndProc=WndProc; //указатель на функцию окна
w.hCursor=LoadCursor(NULL, IDC_ARROW); //загружаем курсор в виде стрелки
w.hIcon=0; //иконки у нас не будет пока
w.lpszMenuName=0; //и меню пока не будет
w.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); //цвет фона окна — белый
w.style=CS_HREDRAW|CS_VREDRAW; //стиль окна — перерисовываемое по х и по у
w.cbClsExtra=0;
w.cbWndExtra=0;
//Если не удалось зарегистрировать класс окна — выходим
if(!RegisterClass(&w))
return 0;
//Создадим окно в памяти, заполнив аргументы CreateWindow
hWnd=CreateWindow(szProgName, //Имя программы
"Моя первая программа!", //Заголовок окна
WS_OVERLAPPEDWINDOW, //Стиль окна — перекрывающееся
100, //положение окна на экране по х
100, //по у
500, //размеры по х
400, //по у
(HWND)NULL, //идентификатор родительского окна
(HMENU)NULL, //идентификатор меню
(HINSTANCE)hInstance, //идентификатор экземпляра программы
(HINSTANCE)NULL); //отсутствие дополнительных параметров
//Выводим окно из памяти на экран
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; //создаём контекст устройства
PAINTSTRUCT ps; //создаём экземпляр структуры графического вывода
//Цикл обработки сообщений
switch(messg)
{
//сообщение рисования
case WM_PAINT :
//начинаем рисовать
hdc=BeginPaint(hWnd, &ps);
//здесь вы обычно вставляете свой текст:
TextOut(hdc, 150,150, "Здравствуй, WIN 32 API!!!!", 26);
//закругляемся
//обновляем окно
ValidateRect(hWnd, NULL);
//заканчиваем рисовать
EndPaint(hWnd, &ps);
break;
//сообщение выхода — разрушение окна
case WM_DESTROY:
PostQuitMessage(0); //Посылаем сообщение выхода с кодом 0 — нормальное завершение
break;
default:
return(DefWindowProc(hWnd, messg, wParam, lParam));
//освобождаем очередь приложения от нераспознаных
}
return 0;
}
Николай, по работе с графикой посмотрите вот эту статью.