Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
A05_API.doc
Скачиваний:
5
Добавлен:
12.11.2019
Размер:
1.3 Mб
Скачать

Int nWidth,

Int nHeight,

HWND hWndParent,

HMENU hMenu,

HINSTANCE hInstance,

LPVOID lParam

).

Все параметры этой функции, кроме первого, имеют тот же смысл, что и у функции CreateWindow. Первый параметр, dwExStyle, задает расширенный стиль окна, применяемый совместно со стилем, определенным в параметре dwStyle. Например, в качестве расширенного стиля можно задать один или несколько флагов, приведенных в таблице 5.10.

Таблица 5.10. Расширенные стили окна

Стиль

Описание

WS_EX_ACCEPTFILES

Создать окно, которое принимает перетаскиваемые файлы

WS_EX_CLIENTEDGE

Рамка окна имеет утопленный край

WS_EX_CONTROLPARENT

Разрешить пользователю перемещаться по дочерним окнам с помощью клавиши Tab

WS_EX_MDICHILD

Создать дочернее окно многодокументного интерфейса

WS_EX_STATICEDGE

Создать окно с трехмерной рамкой. Этот стиль прежназначен для элементов, которые не принимают ввод от пользователя

WS_EX_TOOLWINDOW

Создать окно с инструментами, предназначенное для реализации плавающих панелей инструментов

WS_EX_TRANSPARENT

Создать прозрачное окно. Любые окна того же уровня, накрываемые этим окном, получат сообщение WM_PARWNT в первую очередь, тем самым создавая эффект прозрачности

WS_EX_WINDOWEDGE

Создать окно, имеющее рамку с акивированным краем

Функция CreateWindowEx так же, как и функция CreateWindow, может быть применена для создания любых окон, в том числе и окон элементов управления Windows.

5.3.5. Отображение окна на экране. Для отображения на экране созданного окна вызывается функция ShowWindow, имеющая следующий прототип:

BOOL ShowWindow (HWND hWnd, int nCmdShow).

Первым параметром функции является дескриптор окна, а второй параметр определяет, в каком виде будет показано окно.

При начальном отображении главного окна рекомендуется присваивать второму параметру то значение, которое передается приложению через параметр nCmdShow функции WinMain.

При последующих отображениях можно использовать любое из значений, приведенных в таблице 5.11.

Таблица 5.11. Часто используемые значения параметра nCmdShow функции ShowWindow

Значение

Описание

SW_HIDE

Скрыть окно

SW_MAXIMIZE

Развернуть окно

SW_MINIMIZE

Свернуть окно

SW_SHOW

Активизировать окно и показать в его текущих размерах и позиции

SW_SHOWMINNOACTIVE

Окно не выводится, а на панели задач появляются его имя и пиктограмма

5.3.6. Обработка сообщений. После вывода на экран программа должна подготовить себя для получения информации от пользователя. Эта информация обычно вводится с помощью клавиатуры или мыши. Windows поддерживает очередь сообщений (message queue) для каждой программы, работающей в системе. Любое действие пользователя система Windows преобразует в сообщение, которое помещается в указанную очередь.

Программа извлекает сообщения из очереди, выполняя блок команд, известный как цикл обработки сообщений (message loop):

while (GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

return msg.wParam;

В этом фрагменте кода переменная msg – это структура типа MSG, которая определена в заголовочных файлах Windows следующим образом:

typedef struct tagMSG

{

HWND hwnd; // дескриптор окна, которому адресовано сообщение

UINT message; // номер (идентификатор) сообщения

WPARAM wParam; // параметр сообщения wParam

LPARAM lParam; // параметр сообщения lParam

DWORD time; // время отправки сообщения

POINT pt; // позиция курсора (в экранных координатах) в момент отправки

// сообщения

} MSG;

Интерпретация параметров wParam и lParam зависит от номера сообщения. Тип данных POINT используется для представления точки парой координат:

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 содержится также идентифицирующая нажатую клавишу информация, которая зависит от аппаратной платформы.

Функция TranslateMessage преобразует пару сообщений WM_KEYDOWN и WM_KEYUP, в сообщение WM_CHAR, которое содержит код символа (wParam) в вид значения типа TCHAR6. Сообщение WM_CHAR помещается в очередь, а на следующей итерации цикла функция GetMessage извлекает его для последующей обработки.

Наконец, функция DispatchMessage передает структуру msg обратно в Windows. Очередной ход – за Windows. Windows отправляет сообщение для его обработки соответствующей оконной процедуре, вызывая ее как функцию обратного вызова.

Следует обратить внимание на то, что сообщение передается оконной процедуре именно того окна, которому оно было адресовано. Это может быть или WndProc (если сообщение адресовано главному окну), или оконная процедура некоторого диалогового окна, или оконная процедура одного из стандартных элементов управления, спрятанная в недрах Windows (то есть в DLL).

После возврата из оконной процедуры Windows передает управление оператору, указанному за вызовом DispatchMessage, т.е на начало цикла while, и работа цикла продолжается.

Как уже говорилось ранее, цикл обработки сообщений функционирует до тех пор, пока из очереди не поступит сообщение WM_QUIT. Появление этого сообщения вызывает немедленный выход из цикла и прекращение работы программы.

5.3.7. Оконная процедура. Реальная работа приложения осуществляется в оконной процедуре (window procedure). Оконная процедура определяет то, что выводится в клиентскую область окна, и то, как окну реагировать на пользовательский ввод.

Заголовок оконной процедуры всегда имеет следующий вид:

LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam).

Четыре параметра оконной процедуры идентичны первым четырем полям структуры MSG. Первый параметр функции содержит дескриптор окна, получающего сообщение. Во втором параметре указывается идентификатор сообщения. Для системных сообщений в Windows зарезервированы номера от 0 до 1024. Третий и четвертый параметры содержат дополнительную информацию, которая распознается системой в зависимости от типа полученного сообщения.

Вместо имени WndProc можно использовать любое другое имя, но оно должно совпадать со значением поля lpfnWndProc структуры wc.

В рассматриваемой программе имеется только одно окно класса MyClass. Дескриптор окна hMainWnd получен вызовом функции CreateWindow. Поэтому при вызове оконной процедуры ее параметру hWnd всегда передается значение hMainWnd. Усли же в программе создается несколько окон на основе одного и того же класса окна (и, следовательно, имеющих одну и ту же оконную процедуру), тогда параметру hWnd будет передаваться дескриптор конкретного окна, получающего сообщение.

Обычно программисты используют оператор switch для определения того, какое сообщение получено и как его обрабатывать. Если сообщение обрабатывается, то оконная процедура обязана вернуть нулевое значение. Все сообщения, не обрабатываемые оконной процедурой, должны передаваться системной функции DefWindowProc. В этом случае оконная процедура должна вернуть то значение, которое возвращает DefWindowProc.

Таким образом, программист пишет код только для тех сообщений, которые нуждаются в нестандартной обработке. В рассмотренной программе таких сообщений всего три: WM_PAINT, WM_CLOSE, WM_DESTROY.

5.3.8. Обработка сообщения WM_PAINT. Обработка сообщения WM_PAINT крайне важна для программирования под управлением Windows. Это сообщение уведомляет программу, что часть или вся клиентская область окна недействительна (invalid) и ее необходимо перерисовать. В каких ситуациях клиентская область становится недействительной? Рассмотрим некоторые случаи.

Очевидно, что при создании окна недействительна вся его клиентская область, поскольку в ней еще ничего не нарисовано. Это один.

Если мы меняем размеры окна, клиентская область также объявляется системой недействительной. Это два.

Когда мы минимизируем окно программы, сворачивая его на панель задач, а затем снова разворачиваем окно до начального размера, то Windows объявляет клиентскую область окна недействительной. Это три.

Если мы перемещаем окна так, что они перекрываются, а затем закрытая часть окна вновь открывается, то Windows помечает требующую восстановления клиентскую область как недействительную. Это четыре.

Список примеров недействительной клиентской области можно продолжить, но ограничимся перечисленными.

Во всех перечисленных случаях, кроме первого, операционная система автоматически помечает клиентскую область окна как недействительную, что влечет за собой посылку сообщения WM_PAINT. В первом случае, когда окно только что было создано, аналогичный эффект достигается вызовом функции ShowWindow. В процессе ее выполнения генерируются сообщения WM_SIZE и WM_MOVE, а обрабатывая WM_SIZE, система автоматически генерирует сообщение WM_PAINT.

Вернемся к анализу нашей программы. Обработку сообщения WM_PAINT рекомендуется всегда начинать с вызова функции BeginPaint:

hDC = BeginPaint (hWnd, &pc);

Первый параметр функции содержит дескриптор окна, полученный через аргумент оконной процедуры, а второй – адрес структуры pc типа PAINTSTRUCT. Поля этой структуры, заполняемые в результате выполнения функции BeginPaint, в дальнейшем используются операционной системой. Для нас сейчас более важно возвращаемое функцией значение – это дескриптор так называемого контекста устройства.

Контекст устройства (device context) описывает физическое устройство вывода информации, например дисплей или принтер. Этот важнейший объект графической подсистемы Windows представлен внутренней структурой данных, сохраняющей часто используемые графические атрибуты, такие как цвет фона, перо, кисть, шрифт и им подобные параметры. Эти атрибуты используются при вызове всех рисующих функций, получающих дескрипто hDC в качестве параметра.

Прежде чем перейти к следующей строке программного текста, отметим два побочных эффекта выполнения функции BeginPaint.

Во-первых, обрабатывая вызов BeginPaint, система Windows обновляет фон клиентской области, если обновляемый регион помечен для стирания7. По умолчанию для этого используется кисть, заданная в поле 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.

В нашей программе все рисование сводится к выводу текста « » при помощи функции DrawText, имеющей следующий прототип:

BOOL DrawText

{

HDC hdc, // дескриптор контекста устройства

LPCTSTR lpString, // указатель на символьную строку

int nCount, // длина текста

LRECT lpRect, // указатель на ограничивающий прямоугольник

UINT uFormat // флаги форматирования текста

};

Функция выводит текст из строки lpString в прямоугольную область, заданную структурой типа RECT, используя метод форматирования, заданный параметром uFormat. Количество символов в выводимой строке задается параметром nCount. Если установить значение nCount в -1, то система сама определит длину строки lpString по завершающему нулевому символу. Но в этом случае программист должен позаботиться о том, чтобы строка действительно завершалась нулевым байтом.

На месте последнего параметра функции задан набор флагов DT_SINGLELINE | DT_CENTER | DT_VCENTER, значения которых определяются в заголовочных файлах Windows. Флаги показывают, что текст будет выводиться в одну строку, по центру относительно горизонтали и вертикали внутри прямоугольной области, заданной четвертым параметром. Благодаря этому текст «» выводится в центре клиентской области.

Когда клиентская область становится недействительной (например, при изменении размеров окна), WndProc получает новое сообщение WM_PAINT. Обрабатывая его, программа вновь вызывает функцию GetClientRect и поэтому рисует текст опять в центре окна.

После окончания работы с графическими функциями в блоке обработки сообщения WM_PAINT необходимо освободить полученный контекст устройства с помощью функции EndPaint.

Следует отметить, что при выводе текста используются текущие установки для шрифта, цвета фона и цвета текста.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]