Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming_Windows_95_Part_I.pdf
Скачиваний:
96
Добавлен:
05.06.2014
Размер:
4.61 Mб
Скачать

43

(invalid rectangle); иногда — "недействительного региона" (invalid region). Если еще один регион рабочей области становится недействительным перед обработкой сообщения WM_PAINT, Windows рассчитывает новый недействительный регион, который содержит оба эти региона и запоминает эту новую информацию в структуре информации о рисовании. Windows не помещает в очередь сообщений сразу несколько сообщений WM_PAINT.

Оконная процедура, вызывая функцию InvalidateRect, может задать недействительный прямоугольник в своей рабочей области. Если в очереди сообщений уже содержится сообщение WM_PAINT, Windows рассчитывает новый недействительный прямоугольник. В противном случае Windows помещает новое сообщение WM_PAINT в очередь сообщений. При принятии сообщения WM_PAINT (как мы позже увидим в этой главе), оконная процедура может получить координаты недействительного прямоугольника. Она также может получить эти координаты в любое другое время, вызвав функцию GetUpdateRect.

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

Введение в графический интерфейс устройства (GDI)

Для рисования в рабочей области вашего окна, вы используете функции графического интерфейса устройства. (Обзор GDI ждет нас в следующей главе). В Windows имеется несколько функций GDI для вывода строк текста в рабочей области окна. В главе 2 вы уже встречались с функцией DrawText, но гораздо более популярной функцией является TextOut. Формат этой функции следующий:

TextOut(hdc, x, y, psString, iLength);

Функция TextOut выводит на экран строку символов. Параметр psString — это указатель на строку символов, а iLength — длина строки символов. Параметры x и y определяют начальную позицию строки символов в рамках рабочей области. (Более подробно об этом будет рассказано в дальнейшем.) Параметр hdc — это "описатель контекста устройства" (handle to a device context), являющийся важной частью GDI. Практически каждой функции GDI в качестве первого параметра необходим этот описатель.

Контекст устройства

Вспомните, описатель — это просто число, которое Windows использует для внутренней ссылки на объект. Вы получаете описатель от Windows и затем используете этот описатель в разных функциях. Описатель контекста устройства — это паспорт вашего окна для функций GDI. Этот описатель дает вам полную свободу при рисовании в рабочей области вашего окна, и вы можете сделать ее такой, как пожелаете.

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

Некоторые значения в контексте устройства являются графическими "атрибутами" (attributes). Эти атрибуты определяют некоторые особенности работы функций рисования GDI. Например, для функции TextOut эти атрибуты контекста устройства задают цвет текста, цвет фона для текста, процедуру преобразования координат x и y, передаваемых функции TextOut в координаты рабочей области, а также шрифт, используемый для вывода текста.

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

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

Получение описателя контекста устройства. Первый метод

Этот метод используется при обработке сообщений WM_PAINT. Применяются две функции: BeginPaint и EndPaint. Для этих двух функций требуется описатель окна (передаваемый в оконную процедуру в качестве параметра) и адрес переменной типа структуры PAINTSTRUCT. Программисты, пишущие программы для Windows, обычно называют эту структурную переменную ps и определяют ее внутри оконной процедуры следующим образом:

44

PAINTSTRUCT ps;

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

HDC hdc;

Тип данных HDC определяется как 32-разрядное беззнаковое целое. Затем программа может использовать функции GDI, например TextOut. Вызов функции EndPaint освобождает описатель контекста устройства.

Типовой процесс обработки сообщения WM_PAINT выглядит следующим образом:

case WM_PAINT:

hdc=BeginPaint(hwnd, &ps);

[использование функций GDI]

EndPaint(hwnd, &ps); return 0;

При обработке сообщения WM_PAINT в оконной процедуре функции BeginPaint и EndPaint должны обязательно вызываться парой. Если в оконной процедуре сообщения WM_PAINT не обрабатываются, то они должны передаваться в DefWindowProc (процедура обработки сообщений по умолчанию), реализованной в Windows.

DefWindowProc обрабатывает сообщения WM_PAINT следующим образом:

case WM_PAINT: BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps); return 0;

Следующие одна за другой функции BeginPaint и EndPaint просто превращают ранее недействительный регион в действительный. Но нельзя делать следующее:

case WM_PAINT:

// ОШИБКА!!!

return 0;

Windows помещает сообщение WM_PAINT в очередь сообщений, поскольку часть рабочей области окна недействительна (требует перерисовки). До тех пор пока вы не вызовете функции BeginPaint и EndPaint (или ValidateRect), Windows не сделает эту область действительной. Вместо этого Windows снова отправит вам сообщение WM_PAINT. И снова, и снова, и снова ...

Структура информации о рисовании

Ранее уже говорилось о структуре информации о рисовании, которая поддерживается в Windows для каждого окна. Это PAINTSTRUCT. Структура определяется так:

typedef struct tagPAINTSTRUCT

{

HDC

hdc;

BOOL

fErase;

RECT

rcPaint;

BOOL

fRestore;

BOOL

fIncUpdate;

BYTE

rgbReserved[32];

} PAINTSTRUCT;

 

Windows заполняет поля этой структуры, когда ваша программа вызывает BeginPaint. Вам в программе можно использовать только первые три поля структуры. Остальные используются Windows.

Поле hdc — это описатель контекста устройства. Возвращаемым значением функции BeginPaint также является описатель контекста устройства, и такая избыточность характерна для Windows.

В подавляющем большинстве случаев, в поле fErase установлен флаг TRUE (т. е., ненулевое значение), означающий, что Windows обновит фон недействительного прямоугольника. Windows перерисует фон, используя кисть, заданную в поле hbrBackground структуры WNDCLASSEX, которую вы использовали при регистрации класса окна во время инициализации WinMain. Многие программы для Windows используют белую кисть:

wndclass.hbrBackground =(HBRUSH) GetStockObject(WHITE_BRUSH);

Однако, если вы, вызывая функцию InvalidateRect, делаете недействительным прямоугольник рабочей зоны вашей программы, то последний параметр этой функции определяет, хотите ли вы стирать фон. Если этот параметр равен FALSE (т. е. 0), Windows не будет стирать фон и поле fErase также будет равно FALSE.

45

Поле rcPaint структуры PAINTSTRUCT — это структура типа RECT. Как вы знаете из главы 2, структура RECT определяет прямоугольник. В ней имеется четыре поля: left, top, right и bottom. Поле rcPaint структуры PAINTSTRUCT определяет границы недействительного прямоугольника, как показано на рис. 3.1. Значения заданы в пикселях относительно левого верхнего угла рабочей области. Недействительный прямоугольник — это та область, которую вы хотите перерисовать. Хотя программа для Windows может просто перерисовать всю рабочую область окна при получении сообщения WM_PAINT, перерисовка только той области окна, которая задана этим прямоугольником, экономит время.

0

left

right

0

top

Invalid rectangle

(недействительный

прямоугольник)

bottom

Client area

(рабочая область)

Рис. 3.1 Границы недействительного прямоугольника

Прямоугольник rcPaint в PAINTSTRUCT — это не только недействительный прямоугольник, это также и "отсекающий" (clipping) прямоугольник. Это означает, что Windows рисует только внутри отсекающего прямоугольника. (Или точнее, если недействительная зона не является прямоугольником, Windows рисует только внутри этой зоны.) Когда вы используете описатель контекста устройства из структуры PAINTSTRUCT, Windows не будет рисовать вне прямоугольника rcPaint.

Чтобы при обработке сообщения WM_PAINT рисовать вне прямоугольника rcPaint, вы можете сделать вызов:

InvalidateRect(hWnd, NULL, TRUE);

перед вызовом BeginPaint. Это сделает недействительной всю рабочую область и обновит ее фон. Если же значение последнего параметра будет равно FALSE, то фон обновляться не будет. Все что там было, останется неизменным.

В программе HELLOWIN из главы 2 мы не думали о недействительных или отсекающих прямоугольниках при обработке сообщения WM_PAINT. Если оказывалось, что область вывода текста на экран находится внутри недействительного прямоугольника, то функция DrawText перерисовывала ее. Если при обработке вызова DrawText Windows не находит такие области, на экран ничего не выводится. Но такой поиск требует времени. Программист, заботящийся об эффективности и быстродействии, захочет при обработке сообщений WM_PAINT использовать размеры недействительного прямоугольника, чтобы не обращаться лишний раз к вызовам GDI.

Получение описателя контекста устройства. Второй метод

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

hdc=GetDC(hwnd);

[использование функций GDI]

ReleaseDC(hwnd, hdc);

46

Также как BeginPaint и EndPaint, функции GetDC и ReleaseDC следует вызывать парой. Если вы при обработке сообщения вызываете GetDC, то перед выходом из оконной процедуры необходимо вызвать ReleaseDC. Не вызывайте GetDC при обработке одного сообщения, а ReleaseDC при обработке другого.

В отличии от описателя контекста устройства, полученного из структуры PAINTSTRUCT, в описателе контекста устройства, возвращаемом функцией GetDC, определен отсекающий прямоугольник, равный всей рабочей области. Вы можете рисовать в любом месте рабочей области, а не только в недействительном прямоугольнике (если недействительный прямоугольник вообще определен). В отличии от BeginPaint, GetDC не делает действительными какие-либо недействительные зоны.

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

Функция TextOut. Подробности

Когда вы получаете описатель контекста устройства, Windows заполняет внутреннюю структуру контекста устройства задаваемыми по умолчанию значениями. Как вы увидите в следующих главах, эти задаваемые по умолчанию значения можно изменить с помощью функций GDI. Из тех функций GDI, которые нас интересуют прямо сейчас, рассмотрим TextOut:

TextOut(hdc, x, y, psString, iLength);

Давайте исследуем эту функцию более подробно.

Первый параметр — это описатель контекста устройства, являющийся возвращаемым значением либо функции GetDC, либо функции BeginPaint, полученный при обработке сообщения WM_PAINT.

Атрибуты контекста устройства управляют характеристиками выводимого на экран текста. Например, один атрибут контекста устройства задает цвет текста. Цвет, задаваемый по умолчанию — черный. Контекст устройства по умолчанию также определяет цвет фона — белый. Когда программа выводит текст на экран, Windows использует этот цвет фона для заполнения прямоугольной зоны вокруг каждого символа, эта зона называется знакоместом (character box).

Цвет фона текста не является цветом фона, который вы установили при определении класса окна. Фон в классе окна — это кисть, являющаяся шаблоном, которая может иметь, а может и не иметь чистый (без полутонов) цвет, и которую Windows использует для закрашивания рабочей области. Фон в классе окна не имеет отношения к структуре контекста устройства. При определении структуры класса окна в большинстве приложений Windows используется кисть WHITE_BRUSH, поэтому задаваемый по умолчанию в контексте устройства цвет фона оказывается таким же, как и цвет кисти, используемой Windows для закрашивания фона рабочей области.

Параметр psString — это указатель на символьную строку, а iLength — длина строки, т. е., число символов в строке. Строка не должна содержать никаких управляющих символов ASCII, таких как возврат каретки, перевод строки, табуляция или забой. Windows выводит такие управляющие символы в виде прямоугольников или закрашенных блоков. TextOut не определяет конца строки по нулевому символу, и поэтому для задания ее длины необходим параметр iLength.

Значения x и y в TextOut определяют точку начала строки текста внутри рабочей области. Значение x в горизонтальном направлении, значение y в вертикальном. Левый верхний угол первого символа строки имеет координаты

(x, y). В контексте устройства по умолчанию исходной точкой отсчета (когда x и y равны 0) является левый верхний угол рабочей области. Если x и y в TextOut равны 0, строка текста начнет выводиться, начиная с левого верхнего угла рабочей области.

Координаты GDI в документации упоминаются как "логические координаты" (logical coordinates). Что именно это означает, мы более подробно изучим в следующей главе. Сейчас достаточно знать, что в Windows имеются различные "режимы отображения" (mapping mode), которые определяют, как логические координаты, заданные в функциях GDI, преобразуются в реальные физические координаты дисплея. Режим отображения определяется в контексте устройства. Задаваемый по умолчанию режим отображения называется MM_TEXT (идентификатор, заданный в заголовочных файлах Windows). В режиме отображения MM_TEXT логические единицы соответствуют физическим единицам, каковыми являются пиксели, задаваемые относительно левого верхнего угла рабочей области. Значения по координате x увеличиваются при движении вправо по рабочей области, а по y — при движении вниз. (См. рис. 3.2.) Система координат режима MM_TEXT эквивалентна системе координат, которую Windows использует для определения недействительного прямоугольника в структуре PAINTSTRUCT. Это очень удобно. (Однако это не относится к другим режимам отображения).

Соседние файлы в предмете Операционные системы