Программирование в Windows API. Учебное пособие
.pdf3.7 Функция UpdateWindow
Функция UpdateWindow обновляет содержимое окна:
BOOL UpdateWindow (HWND hWnd); hWnd
Дескриптор окна.
Возвращаемое значение:
при успешном завершении: ненулевое значение;
при ошибке: ноль.
Если клиентская часть окна имеет повреждённую область, функция UpdateWindow непосредственно вызывает оконную функцию (минуя очередь сообщений потока приложения) и передаёт сообщение WM_PAINT.
3.8 Функция GetMessage
Функция GetMessage извлекает очередное сообщение из очереди сообщений вызывающего потока и записывает полученные данные в специальную структуру типа MSG:
BOOL GetMessage (LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);
lpMsg
Адрес структуры MSG, которая получает данные о сообщении из очереди сообщений потока.
hWnd
Дескриптор окна, для которого должны быть получены сообщения. Окно должно принадлежать вызывающему потоку. Если параметр равен NULL, принимаются сообщения для всех окон потока.
wMsgFilterMin
Целочисленное значение минимального номера принимаемого сообщения.
31
wMsgFilterMax
Целочисленное значение максимального номера принимаемого сообщения.
Если wMsgFilterMin и wMsgFilterMax равны нулю,
принимаются все сообщения.
Возвращаемое значение:
если код сообщения не равен WM_QUIT, при успешном завершении: положительное значение;
если код сообщения равен WM_QUIT: ноль;
при возникновении ошибки: -1.
Структура MSG содержит следующие поля:
hwnd
Дескриптор окна, оконная функция которого получает сообщение.
message
Идентификатор сообщения. wParam, lParam
Целые числа, используемые для передачи дополнительных данных. Значения зависят от конкретного сообщения message.
time
Время, когда сообщение было отправлено.
pt
Позиция курсора в оконных координатах в момент передачи сообщения.
3.9 Функция DispatchMessage
Функция DispatchMessage вызывает оконную функцию и передаёт дескриптор окна, код сообщения и дополнительные параметры, получаемые из структуры
MSG:
LRESULT DispatchMessage (CONST MSG *lpMsg);
32
lpMsg
Адрес структуры MSG, которая содержит данные о сообщении.
Возвращаемое значение:
соответствует значению, которое возвратила оконная функция после обработки текущего сообщения; обычно не используется.
Структура MSG должна содержать действительную информацию о сообщении. Если передано сообщение WM_TIMER и параметр lParam не равен NULL, то он содержит указатель на функцию, которая вызывается вместо оконной функции.
3.10 Функция PostQuitMessage
Функция PostQuitMessage указывает системе, что поток сделал запрос на завершение (выход):
void PostQuitMessage (int nExitCode);
nExitCode
Код выхода приложения, используется как значение параметра wParam сообщения WM_QUIT.
Функция помещает в очередь сообщений потока сообщение WM_QUIT и немедленно возвращает управление. Когда поток принимает данное сообщение, он выполняет выход из текущего цикла обработки сообщений.
Ниже приведён пример программы, создающей два окна с разными классами и оконными функциями. Левое окно реагирует на двойной щелчок левой клавиши мыши и на нажатие клавиатуры. Правое окно реагирует на одиночный щелчок левой клавиши мыши и на отпускание
33
клавиатуры. Реагирование на все сообщения заключается в выводе на экран информационного окна.
4. Пример программы, создающей два окна с разными классами и оконными функциями
/*************************************************/
/* |
lab1_2wind |
*/ |
/* |
========== |
*/ |
/*Создание двух окон с разными оконными функциями*/
/*************************************************/ #include <windows.h>
HINSTANCE hi_app;
HWND hwnd1,hwnd2;
char *ClassName_left = "WindowClassName_left", *ClassName_right = "WindowClassName_right" ;
BOOL RegisterWndClasses (void); void UnregisterWndClasses (void); BOOL CreateWindows (void);
LRESULT CALLBACK WindowProc_left (HWND, UINT, WPARAM, LPARAM);
34
LRESULT CALLBACK WindowProc_right (HWND, UINT, WPARAM, LPARAM);
BOOL MainOnDestroy (HWND);
BOOL InitializeApp (void); void UninitializeApp (void); int APIENTRY WinMain
(HINSTANCE, HINSTANCE, LPSTR, int); /*************************************************/
/* |
RegisterWndClasses |
*/ |
/* |
================== |
*/ |
/* |
Регистрация классов окон |
*/ |
/*************************************************/ BOOL RegisterWndClasses ()
{ |
|
|
WNDCLASSEX wce_main; |
|
|
memset (&wce_main, 0, |
sizeof(WNDCLASSEX)); |
|
// Класс левого окна |
|
|
wce_main.cbSize |
= |
sizeof(WNDCLASSEX); |
wce_main.hInstance |
= |
hi_app; |
wce_main.style |
= |
CS_VREDRAW | CS_HREDRAW | |
|
|
CS_DBLCLKS; |
wce_main.lpfnWndProc= (WNDPROC)WindowProc_left; |
||
wce_main.hCursor |
= |
LoadCursor(NULL,IDC_ARROW); |
wce_main.hbrBackground = |
||
(HBRUSH)GetStockObject(GRAY_BRUSH); |
||
wce_main.lpszClassName = ClassName_left; |
||
if (! RegisterClassEx(&wce_main)) |
||
return FALSE; |
|
|
// Класс правого окна |
|
|
wce_main.cbSize |
= |
sizeof(WNDCLASSEX); |
wce_main.hInstance |
= |
hi_app; |
wce_main.style |
= |
CS_VREDRAW | CS_HREDRAW | |
|
|
CS_DBLCLKS; |
wce_main.lpfnWndProc= |
(WNDPROC)WindowProc_right; |
|
wce_main.hCursor |
= |
LoadCursor(NULL,IDC_ARROW); |
wce_main.hbrBackground = |
||
(HBRUSH)(COLOR_ACTIVECAPTION+1); wce_main.lpszClassName = ClassName_right;
return RegisterClassEx (&wce_main);
}
35
/*************************************************/
/* |
CreateWindows |
*/ |
/* |
============= |
*/ |
/* |
Функция создания окон |
*/ |
/*************************************************/ BOOL CreateWindows ()
{
int scrw = GetSystemMetrics(SM_CXSCREEN) , scrh = GetSystemMetrics(SM_CYSCREEN);
hwnd1 = CreateWindow( ClassName_left,
"Левое окно.(Двойн. щелчок лев. кл. мыши или нажать клавишу)", WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_VISIBLE, 0, 0 ,
scrw/2, scrh, NULL, NULL, hi_app, 0 );
if (! hwnd1) return FALSE;
hwnd2 = CreateWindow( ClassName_right,
Правое окно.(Щелчок лев. кл. мыши или отпустить клавишу)", WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX |
WS_MAXIMIZEBOX | WS_THICKFRAME | WS_VISIBLE, scrw/2, 0 , scrw/2, scrh , NULL, NULL, hi_app, 0 );
if (! hwnd2) return FALSE;
return TRUE;
}
36
/*************************************************/
/* |
WindowProc_left |
*/ |
/* |
=============== |
*/ |
/* |
Оконная функция левого окна |
*/ |
/*************************************************/ LRESULT CALLBACK WindowProc_left
(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY: return MainOnDestroy (hwnd);
//Нажата левая клавиша мыши
//case WM_LBUTTONDOWN : case WM_LBUTTONDBLCLK :
MessageBox (NULL, "Левое окно",
"сообщение", MB_OK);
break;
// Нажата клавиша на клавиатуре case WM_KEYDOWN:
MessageBox (NULL, "Клавиаша нажата. Выход из программы!", "сообщение", MB_OK);
PostQuitMessage (0); break;
default:
return DefWindowProc (hwnd, msg, wParam, lParam);
}
return 0L;
}
37
/************************************************/
/* |
WindowProc_right |
*/ |
/* |
================ |
*/ |
/* |
Оконная функция правого окна |
*/ |
/************************************************/ LRESULT CALLBACK WindowProc_right
(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY: return MainOnDestroy (hwnd);
// Нажата левая клавиша мыши case WM_LBUTTONDOWN:
MessageBox (NULL, "Правое окно", "сообщение", MB_OK);
break;
// Отпущена клавиша на клавиатуре case WM_KEYUP:
MessageBox (NULL, "Клавиша отпущена!", "сообщение" , MB_OK);
break;
default:
return DefWindowProc (hwnd, msg, wParam, lParam);
}
return 0L;
}
BOOL MainOnDestroy (HWND hwnd)
{
PostQuitMessage (0); return TRUE;
}
38
BOOL InitializeApp ()
{
if (! RegisterWndClasses()) {
MessageBox (NULL, "Ошибка регистрации классов окон.", "сообщение", MB_OK);
return FALSE;
}
CreateWindows ();
return TRUE;
}
void UninitializeApp ()
{
UnregisterClass (ClassName_left , hi_app); UnregisterClass (ClassName_right, hi_app);
}
int APIENTRY WinMain (HINSTANCE hi_crr,
HINSTANCE hi_prv, LPSTR pc_cmdLine, int cmdShow)
{
MSG msg;
hi_app = hi_crr; InitializeApp ();
while (GetMessage (&msg, NULL, 0, 0)) DispatchMessage (&msg);
UninitializeApp ();
return msg.wParam;
}
39
5. Организация вывода информации в окно
с помощью интерфейса графических устройств GDI
Любая система графического интерфейса базируется на некоторой графической подсистеме. В ОС Windows
используется т.н. интерфейс графических устройств, GDI (Graphics Device Interface, Graphical Device Interface),
который предоставляет единый механизм вывода информации в окно, файл специального формата (метафайл), специальную область памяти, а также на другие графические устройства (например, принтер).
Контекст графического устройства – набор настроек и свойств, связанных с определённой поверхностью графического вывода. ОС предоставляет программе возможность обращаться к контексту устройства для выполнения его настройки под конкретные нужды. Контексты устройств относятся к т.н. разделяемым ресурсам, т.е. некоторый контекст в конкретный момент времени как правило может быть доступен только одному приложению. Для выполнения вывода на устройство необходимо сначала запросить у ОС дескриптор контекста устройства, а после завершения вывода – освободить полученный контекст.
Объект GDI – специализированное средство графического вывода, поддерживаемое операционной системой. К основным объектам GDI относятся перо,
кисть, шрифт, палитра, битовое изображение, область.
Данные об объектах GDI ОС хранит в специальных таблицах, размер которых ограничен. ОС предоставляет прикладным программам несколько готовых к использованию системных объектов GDI (белое перо, сплошную белую кисть и др.).
В процессе работы приложение запрашивает и освобождает контексты устройств, создаёт и удаляет
40
