HDevNames
hDevNames
Идентификатор глобального блока памяти, содержащего структуру типа DEVNAMES, содержащей три текстовые строки. Первая строка определяет имя драйвера принтера, вторая - имя принтера, и третья - имя порта вывода, к которому подключен принтер.
Если содержимое этого поля указать как NULL, после возвращения из функции PrintDlg поле будет содержать идентификатор глобального блока памяти, заказанного функцией для структуры DEVNAMES. В структуре будут находиться строки, соответствующие выбранному принтеру.
HInstance
hInstance
Идентификатор модуля, который содержит шаблоны диалоговых панелей. Используется только в том случае, если указаны флаги PD_ENABLEPRINTTEMPLATE или PD_ENABLESETUPTEMPLATE.
HPrintTemplate
hPrintTemplate
Идентификатор блока памяти, содержащего предварительно загруженный шаблон диалоговой панели "Print". Для использования этого поля необходимо указать флаг PD_ENABLEPRINTTEMPLATEHANDLE.
HSetupTemplate
hSetupTemplate
Идентификатор блока памяти, содержащего предварительно загруженный шаблон диалоговой панели "Print Setup". Для использования этого поля необходимо указать флаг PD_ENABLESETUPTEMPLATEHANDLE.
HwndOwner
hwndOwner
Идентификатор окна, создавшего диалоговую панель. Если в поле Flags не указано значение PD_SHOWHELP, в поле hwndOwner можно указать NULL.
Информационный контекст
Информационный контекст
Если приложению необходимо получить информацию об устройстве вывода (например, с помощью функции GetDeviceCaps, рассмотренной нами в 11 томе "Библиотеки системного программиста"), оно может создать вместо обычного информационный контекст . Информационный контекст нельзя использовать для рисования, однако он занимает меньше места в памяти.
Информационный контекст создается при помощи функции CreateIC , аналогичной по своим параметрам функции CreateDC: HDC WINAPI CreateIC( LPCSTR lpszDriver, // имя драйвера LPCSTR lpszDevice, // имя устройства LPCSTR lpszOutput, // имя файла или порта вывода const void FAR* lpvInitData); // данные для инициализации
После использования информационный контекст следует удалить, вызвав функцию DeleteDC.
Использование встроенной кисти
Использование встроенной кисти
Для выбора одной из встроенной кисти вы можете воспользоваться макрокомандой GetStockBrush , определенной в файле windowsx.h: #define GetStockBrush(i) ((HBRUSH)GetStockObject(i))
В качестве параметра для этой макрокоманды можно использовать следующие значения:
Изображение bitmap
Изображение bitmap
В контекст отображения можно выбрать изображение bitmap и затем отобразить его в окне или использовать в меню. Мы будем обсуждать изображения bitmap в отдельной главе этого тома. Сейчас отметим, что по умолчанию в контекст отображения не выбирается никакое изображение bitmap. Приложение должно выбрать его самостоятельно, используя функцию SelectObject . В программном интерфейсе GDI имеются и другие функции для работы с изображениями bitmap. Это функции CreateBitmap , CreateBitmapIndirect , CreateCompatibleBitmap .
Приложения Windows широко пользуются изображениями bitmap, так как они очень удобны для отображения небольших пиктограмм или больших и сложных многоцветных рисунков, полученных при помощи специальных графических редакторов или сканеров. Заметим, что в предыдущих томах "Библиотеки системного программиста" мы использовали изображения bitmap для кнопок и органа управления Toolbar, отложив подробное их изучение на потом.
Кисть
Кисть
Для закрашивания внутренней области окна приложения или замкнутой геометрической фигуры можно использовать не только различные цвета, но и графические изображения небольшого (8х8 пикселов) размера - кисти (brush ).
В предыдущих томах "Библиотеки системного программиста" мы использовали кисть для закрашивания внутренней области окна, указав ее при регистрации класса окна. Вы можете выбрать в контекст отображения предопределенную в Windows или свою кисть, использовав ее для закраски внутренних областей фигур или окна приложения. По умолчанию в контекст отображения выбрана кисть белого цвета.
Для выбора кисти предназначены функции CreateSolidBrush , CreateHatchBrush , CreatePatternBrush , CreateDIBPatternBrush , CreateBrushIndirect , SelectObject .
Кисти
Кисти
Внутренняя область окна и замкнутых геометрических фигур может быть закрашена при помощи кисти. С помощью функции GetStockObject можно выбрать черную, белую, темно- или светло-серую кисть или нулевую кисть (null brush). Можно выбрать одну из кистей, предназначенных для штриховки (Рисунок 1.4), для чего следует использовать функцию CreateHatchBrush. Все эти кисти встроены в операционную систему.
Комбинирование областей
Комбинирование областей
Функция CombineRegion позволяет вам изменить существующую область, скомбинировав ее из двух других: int WINAPI CombineRgn( HRGN hrgnDest, // новая область HRGN hrgnSrc1, // первая исходная область HRGN hrgnSrc2, // вторая исходная область int fnCombineMode); // режим комбинирования
Перед вызовом функции вам надо определить все три области. Функция объединит области hrgnSrc1 и hrgnSrc2, изменив соответствующим образом область hrgnDest.
Способ комбинирования областей зависит от значения параметра fnCombineMode:
Контекст для метафайла
Контекст для метафайла
Контекст для метафайла позволяет записывать команды GDI в файл и затем проигрывать такой файл на физическом устройстве вывода. Файл может находиться в памяти или на диске, в последнем случае его можно использовать для переноса графического изображения в другое приложение.
Для создания контекста метефайла используется функция CreateMetaFile : HDC WINAPI CreateMetaFile(LPCSTR lpszFileName);
Параметр lpszFileName должен указывать на строку, содержащую путь к имени файла, в который будут записаны команды GDI, или NULL. В последнем случае создается метафайл в оперативной памяти.
После выполнения рисования в контексте метафайла следует закрыть метафайл, вызвав функцию CloseMetaFile : HMETAFILE WINAPI CloseMetaFile(HDC hdc);
Эта функция закрывает метафайл для контекста hdc и возвращает идентификатор метафайла. Идентификатор закрытого метафайла использовать нельзя, так как он не содержит никакой полезной информации.
Что можно сделать с полученным идентификатором метафайла?
Можно скопировать метафайл в обычный дисковый файл, вызвав функцию CopyMetaFile : HMETAFILE WINAPI CopyMetaFile(HMETAFILE hmf, LPCSTR lpszFileName);
Параметр hmf определяет метафайл, параметр lpszFileName содержит путь к имени файла, в который будет записан метафайл .
Можно проиграть метафайл в контексте отображения или контексте устройства, вызвав функцию PlayMetaFile : BOOL WINAPI PlayMetaFile(HDC hdc, HMETAFILE hmf);
Наконец, при помощи функции DeleteMetaFile можно удалить метафайл: BOOL WINAPI DeleteMetaFile(HMETAFILE hmf);
Удаление метафайла с помощью функции DeleteMetaFile делает недействительным идентификатор метафайла hmf и освобождает оперативную память, занятую метафайлом. Если метафайл был создан как обычный дисковый файл, функция DeleteMetaFile не удаляет его с диска.
Для того чтобы воспользоваться метафайлом, хранящимся в виде дискового файла, его следует загрузить при помощи функции GetMetaFile , указав ей в качестве единственного параметра путь к соответствующему файлу: HMETAFILE WINAPI GetMetaFile(LPCSTR lpszFileName);
Контекст для памяти
Контекст для памяти
В работе с битовыми изображениями bitmap часто используется такое "устройство вывода", как оперативная память. Приложение может полностью подготовить изображение в оперативной памяти, получив контекст для памяти , и затем быстро вывести готовое изображение на экран. Этот способ во многих случаях работает намного быстрее и приятнее для пользователя, чем формирование изображения непосредственно на экране.
Контекст для памяти создается совместимым с тем контекстом отображения, в котором будет выполняться вывод на физическое устройство. Для создания совместимого контекста используется функция CreateCompatibleDC : HDC WINAPI CreateCompatibleDC(HDC hdc);
Созданный таким образом контекст памяти удаляется при помощи функции DeleteDC.
Использование контекста памяти будет подробно описано в главе, посвященной битовым изображениям bitmap.
Контекст для устройства DISPLAY
Контекст для устройства DISPLAY
В некоторых случаях требуется получить контекст отображения, позволяющий приложению рисовать в любом месте экрана дисплея. Такой контекст можно создать при помощи функции CreateDC, указав в качестве имени драйвера строку "DISPLAY ", а в качестве остальных параметров - значение NULL: hdc = CreateDC("DISPLAY", NULL, NULL, NULL);
В данном случае будет создан контекст для видеомонитора, с помощью которого приложение может рисовать в любом месте экрана. Начало системы координат, выбранной в данный контекст, располагается в верхнем левом углу экрана видеомонитора.
После использования созданный таким образом контекст отображения следует удалить, вызвав функцию DeleteDC.
Есть еще два способа получения контекста для экрана.
Приложение может получить контекст отображения для всего экрана при помощи функции GetDC, указав в качестве параметра значение NULL: hdc = GetDC(NULL);
Полученный таким образом контекст следует освободить после использования при помощи функции ReleaseDC, передав ей вместо идентификатора окна значение NULL: ReleaseDC(NULL, hdc);
Еще один способ связан с использованием функции GetDCEx, описание которой будет приведено ниже.
Контекст физического устройства
Контекст физического устройства
Вывод изображений на такое устройство, как принтер, может выполняться с использованием тех же приемов, что и вывод в окно приложения. Прежде всего необходимо получить контекст устройства . Затем можно вызывать функции GDI, выполняющие рисование, передавая им идентификатор полученного контекста в качестве параметра.
В отличие от контекста отображения, контекст физического устройства не получается, а создается, для чего используется функция CreateDC : HDC WINAPI CreateDC( LPCSTR lpszDriver, // имя драйвера LPCSTR lpszDevice, // имя устройства LPCSTR lpszOutput, // имя файла или порта вывода const void FAR* lpvInitData); // данные для инициализации
Параметр lpszDriver является указателем на строку символов, содержащую имя драйвера, обслуживающего физическое устройство. Имя драйвера совпадает с именем файла *.drv, содержащего сам драйвер и расположенного в системном каталоге Windows.
Имя устройства lpszDevice - это название самого устройства, описанное, например, в файле win.ini в разделе [devices].
Параметр lpszOutput указывает на структуру данных типа DEVMODE, используемую при инициализации устройства вывода. Если при работе с устройством нужно использовать параметры, установленные при помощи приложения Control Panel, параметр lpszOutput следует указать как NULL.
Более подробно вопросы работы с принтером будут рассмотрены в отдельной главе этого тома.
В приведенном ниже примере создается контекст устройства для лазерного принтера HP Laserjet III, подключенного к порту LPT1:, причем в системном каталоге Windows для этого принтера установлен драйвер hppcl5a.drv: hdc = CreateDC("hppcl5a", "HP LaserJet III", "LPT1:", NULL);
Аналогично, для принтера Epson FX-850, подключенного к порту LPT2:, и работающему через драйвер epson9.drv: hdc = CreateDC("epson9", "Epson FX-850", "LPT2:", NULL);
Созданный при помощи функции CreateDC контекст устройства следует удалить (но не освободить), вызвав функцию DeleteDC: BOOL WINAPI DeleteDC(HDC hdc);
Эта функция возвращает TRUE при нормальном завершении и FALSE при возникновении ошибки.
Контекст отображения для класса окна
Контекст отображения для класса окна
Общий контекст отображения , описанный нами в предыдущем разделе, кешируется операционной системой Windows для ускорения доступа к нему. Однако вы можете создать такой контекст отображения, который хранится отдельно в единственном экземпляре и используется всеми окнами, созданными на базе класса окна. При регистрации такого класса окна вы должны указать стиль CS_CLASSDC : wc.style = CS_CLASSDC;
Все окна, созданные на базе класса, имеющего стиль CS_CLASSDC, будут использовать один общий контекст отображения.
В отличие от общего контекста отображения, приложения, однажды получив контекст отображения для класса окна, могут не освобождать его. То есть для контекста этого типа после функций BeginPaint и GetDC можно не вызывать функции EndPaint и ReleaseDC. Если же приложение вызовет функцию EndPaint или ReleaseDC, они не будут ничего делать и сразу вернут управление. Для уменьшения вероятности ошибки мы рекомендуем вам всегда освобождать контекст отображения, даже если это и не требуется для данного типа контекста.
Несмотря на то, что для всех окон, созданных на базе класса стиля CS_CLASSDC, создается один контекст отображения, не следует думать, что приложение, однажды получив этот контекст, не должно получать его вновь при очередном вызове обработчика сообщения, выполняющего рисование.
Дело в том, что при получении контекста отображения для окна в нем устанавливаются атрибуты области ограничения и начало системы физических координат устройства отображения. Если на базе нашего класса создано несколько окон, при получении ими контекста отображения эти атрибуты "настраиваются" на окно, получившее контекст отображения. Но если на базе класса стиля CS_CLASSDC приложение создало только одно окно, оно может получить контекст отображения для класса окна один раз и не освобождать его.
Зачем используется контекст отображения класса окна?
Вы можете использовать его в тех случаях, когда по соображениям повышения производительности нежелательно выполнять настройку многочисленных атрибутов контекста отображения после каждого вызова функции BeginPaint или EndPaint. Эту настройку можно выполнить только один раз. Каждый раз, когда функция окна получает контекст отображения класса окна, в нем выполняется настройка только двух атрибутов - области ограничения и начала системы физических координат устройства вывода. Остальные атрибуты остаются без изменений и, следовательно, не требуют повторной настройки.
Контекст отображения для окна
Контекст отображения для окна
Все описанные выше контексты отображения позволяют рисовать только во внутренней области окна (client region). С помощью функции GetWindowDC приложение может получить контекст отображения для окна , позволяющий рисовать в любом месте окна (в области заголовка окна, в области системного меню, рамки окна, кнопок изменения размера и т. п.).
Контекст отображения, полученный для окна, используется аналогично общему контексту отображения. После получения контекста его атрибуты принимают значения по умолчанию. Приложение обязано освобождать этот контекст сразу после использования, вызывая функцию ReleaseDC.
Особенностью данного контекста является то, что в нем выбрана система координат, начало которой находится в левом верхнем углу окна (всего окна, а не его внутренней области).
Такой контекст может использоваться при необходимости заменить стандартные элементы окна (заголовок, полосы просмотра и т. п.) на собственные, или если приложение желает нарисовать что-нибудь в области заголовка или рамки.
LCustData
lCustData
Произвольные данные, которые приложение может передать функции фильтра.
LfCharSet
lfCharSet
Набор символов.
Можно использовать одну из следующих констант, определенных в файле windows.h:
LfClipPrecision
lfClipPrecision
Поле используется для определения способа, при помощи которого обрезается изображение символа, частично попавшего за пределы области ограничения вывода (clipping region), выбранную в контекст отображения.
Можно использовать следующие константы: CLIP_DEFAULT_PRECIS , CLIP_CHARACTER_PRECIS , CLIP_STROKE_PRECIS , CLIP_MASK , CLIP_LH_ANGLES , CLIP_TT_ALWAYS , CLIP_EMBEDDED .
Если указана константа CLIP_LH_ANGLES , направление вращения текста зависит от установленного режима отображения.
LfEscapement
lfEscapement
Угол между базовой линией шрифта и координатной осью X в десятых долях градуса (угол отсчитывается в направлении против часовой стрелки).
Если в процессе отображения логического шрифта на физический будет выбран растровый или векторный шрифт, текст будет выведен в горизонтальном направлении, так как вращать можно только шрифты True Type и векторные шрифты.
LfFaceName
lfFaceName
Строка, закрытая двоичным нулем, которая служит названием внешнего вида шрифта. Размер строки (включая закрывающий строку нуль) не должен превышать LF_FACESIZE байт.
Вы можете указать, что вам нужен, например, шрифт "Arial", однако это вовсе не гарантирует, что именно этот шрифт будет предоставлен в распоряжение приложения.
LfHeight
lfHeight
Высота шрифта в логических единицах (зависят от установленного режима отображения).
Можно указывать положительные и отрицательные значения, а также нуль. Если указано нулевое значение, выбирается шрифт размером в 12 пунктов (значение по умолчанию).
Положительные значения определяют высоту ячеек, в которых располагается буква, что соответствует содержимому поля tmHeight структуры TEXTMETRICS.
Абсолютная величина отрицательного значения определяет высоту символов, т.е. tmHeight - tmInternalLeading.
LfItalic
lfItalic
Если содержимое этого поля не равно нулю, запрашивается шрифт с наклонными буквами.
LfOrientation
lfOrientation
Это поле определяет ориентацию символов шрифта. К сожалению, операционная система Windows версии 3.1 игнорирует поле lfOrientation.
LfOutPrecision
lfOutPrecision
Требуемая степень соответствия параметров шрифта.
Это поле используется для того, чтобы указать GDI способ выбора между двумя шрифтами, имеющими одинаковое название, но разный тип. Например, для удовлетворения запроса можно использовать растровый или масштабируемый шрифт с названием OddType. Если в поле lfOutPrecision указать константу OUT_TT_PRECIS, будет выбран масштабируемый шрифт.
Можно указывать одну из следующих констант:
LfPitchAndFamily
lfPitchAndFamily
С помощью этого поля можно определить, нужна ли фиксированная или переменна ширина символов. Кроме этого, можно определить семейство, к которому должен принадлежать полученный шрифт.
Фиксированная или переменная ширина символов задается при помощи следующих констант:
LfQuality
lfQuality
Качество шрифта, полученного при отображении.
Можно указывать одну из следующих констант:
LfStrikeOut
lfStrikeOut
Если содержимое этого поля не равно нулю, запрашивается шрифт с перечеркнутыми буквами.
LfUnderline
lfUnderline
Если содержимое этого поля не равно нулю, запрашивается шрифт с подчеркиванием букв.
LfWeight
lfWeight
Вес шрифта. Определяет жирность символов шрифта и может находиться в пределах от 0 до 1000. Файл windows.h содержит определение символических констант для этого поля:
LfWidth
lfWidth
Ширина символов в логических единицах.
Если указано нулевое значение, используется значение по умолчанию, которое зависит от высоты шрифта и отношения масштабов по осям координат (aspect ratio) для шрифта и устройства вывода.
Личный контекст отображения
Личный контекст отображения
Указав в стиле класса окна значение CS_OWNDC , можно добиться того, что для каждого окна, созданного на базе такого класса, Windows создаст отдельную структуру контекста отображения: wc.style = CS_OWNDC;
Личный контекст отображения можно, получив один раз, никогда не освобождать. Вы можете один раз настроить атрибуты контекста отображения сразу после получения самого контекста и использовать полученный контекст без изменений до завершения работы приложения.
Однако не будет ошибкой, если приложение будет использовать личный контекст отображения как общий, то есть каждый раз при обработке сообщения WM_PAINT (или другого сообщения, обработчик которого занимается рисованием) оно будет получать контекст и затем отдавать его. Соответствующие функции (BeginPaint, EndPaint, GetDC, ReleaseDC) будут возвращать управление, не выполняя никаких действий.
Личный контекст проще в использовании, так как его можно получать и настраивать только один раз, однако оперативная память будет расходоваться менее экономно.
Литература
Литература
Фролов, Г. В. Фролов. Библиотека системного программиста. Тома 11-13. Операционная система Microsoft Windows 3.1 для программиста. Часть 1-3. Москва, "Диалог-МИФИ", 1994 Charles Petzold. Programming Windows 3.1. Microsoft Press. One Microsoft Way. Redmont, Washington, 1992 Brent Rector. Developing Windows 3.1 Applications with Microsoft C/C++. SAMS, 1992 Daniel A. Norton. Writing Windows Device Drivers. Addison-Wesley Publishing Company, 1992 Фролов, Г. В. Фролов. Библиотека системного программиста. Том 6. Защищенный режим процессоров Intel 80286/80386/80486. Москва, "Диалог-МИФИ", 1993 Windows. Справочник для программистов. Версия 3.0. Часть 1, 2. Москва, "Научный центр", 1991 Гладков, Г. В. Фролов. Программирование в Microsoft Windows. Часть 2. Москва, "Диалог-МИФИ", 1992 Эллис, Б. Строуструп. Справочное руководство по языку программирования C++ с комментариями. Москва, МИР, 1992 Фролов, Г. В. Фролов. Персональный компьютер. Шаг за шагом.. Том 2. Операционная система Microsoft Windows 3.1. Москва, "Диалог-МИФИ", 1994 Фролов, Г. В. Фролов. Библиотека системного программиста. Том 10. Компьютер IBM PC/AT, MS-DOS и Windows. Вопросы и ответы. Москва, "Диалог-МИФИ", 1994
Логическая система координат
Логическая система координат
Приложения Windows могут использовать одну из нескольких логических координат , устанавливая соответствующий режим отображения в контексте отображения. При этом, как мы уже говорили, можно использовать любое направление координатных осей и любое расположение начала координат. Например, возможна система координат, в которой задаются положительные и отрицательные координаты по любой оси (Рисунок 2.2).
LpfnPrintHook
lpfnPrintHook
Адрес функции фильтра для диалоговой панели "Print".
LpfnSetupHook
lpfnSetupHook
Адрес функции фильтра для диалоговой панели "Print Setup".
LpPrintTemplateName
lpPrintTemplateName
Адрес текстовой строки, закрытой нулем, содержащей имя ресурса для шаблона диалоговой панели "Print". Для использования этого поля необходимо указать флаг PD_ENABLEPRINTTEMPLATE.
LpSetupTemplateName
lpSetupTemplateName
Адрес текстовой строки, закрытой нулем, содержащей имя ресурса для шаблона диалоговой панели "Print Setup". Для использования этого поля необходимо указать флаг PD_ENABLESETUPTEMPLATE.
LStructSize
lStructSize
Размер структуры PRINTDLG в байтах. Это поле следует заполнить перед вызовом функции PrintDlg.
Масштаб осей для окна
Масштаб осей для окна
Для некоторых режимов отображения приложение может изменять масштаб осей в окне (window extent ), устанавливая для него новое значение в контексте отображения.
По умолчанию используется значение (1,1), т. е. используется масштаб 1:1. Приложение может изменить масштаб осей для окна, вызвав функцию SetWindowExt .
Масштаб осей физических координат
Масштаб осей физических координат
Контекст отображения содержит масштаб осей для физического устройства (viewport extent ), который вместе с масштабом осей в окне используется в процессе преобразования координат.
По умолчанию для масштаба осей физических координат используется значение (1,1), т. е. масштаб 1:1. Приложение может изменить масштаб осей физических координат, вызвав функцию SetViewportExt .
Метрические режимы отображения
Метрические режимы отображения
Режим MM_LOMETRIC , наряду с режимами MM_HIMETRIC , MM_LOENGLISH , MM_HIENGLISH и MM_TWIPS, относится к метрическим режимам. Эти режимы отображения позволяют использовать привычные единицы измерения, такие как миллиметры и дюймы.
В метрических режимах отображения используются полные формулы преобразования координат, приведенные выше в разделе "Преобразование координат". В этих формулах приложение может изменять переменные, определяющие смещение начала физической или логической системы координат xViewOrg, yViewOrg, xWinOrg и yWinOrg.
Приложение не может изменить значения переменных xViewExt, yViewExt, xWinExt и yWinExt, от которых зависит масштаб по осям координат. Отношения xViewExt/xWinExt и yViewExt/yWinExt имеют фиксированное значение для каждого из метрических режимов отображения.
Заметим, что для этих режимов отношение yViewExt/yWinExt имеет отрицательный знак, в результате чего ось Y оказывается направленной снизу вверх.
Обратим ваше внимание на одно важное обстоятельство, связанное с использованием метрических режимов отображения.
Сразу после переключения в метрический режим отображения система координат примет достаточно странный вид (Рисунок 2.4).
Начальные координаты кисти
Начальные координаты кисти
Начальные координаты кисти (brush origin ) используются для определения координат точки внутри кисти, которая будет служить начальной при закраске внутренней области фигуры или окна. По умолчанию используются координаты (0,0), соответствующие верхнему левому углу кисти (в системе координат, выбранной в контекст отображения по умолчанию).
Приложение может изменить начальные координаты кисти при помощи функций SetBrushOrg и UnrealizeObject .
Начало системы физических координат
Начало системы физических координат
Начало системы физических координат (viewport origin ) относится не к окну приложения, а к физическому устройству вывода (например, ко всему экрану монитора) и используется при выполнении преобразования логических координат в физические.
По умолчанию начало системы физических координат установлено в точку (0,0). Для перемещения начала системы координат окна можно использовать функцию SetViewportOrg .
Начало системы координат для окна
Начало системы координат для окна
В контексте отображения хранится информация о расположении начала системы координат для окна и для физического устройства отображения. Эта информация используется GDI при выполнении преобразования логических координат в физические, которое выполняется различными способами в зависимости от установленного режима отображения. Подробнее этот вопрос будет рассмотрен при описании систем координат, доступных для приложений Windows версии 3.1.
По умолчанию начало системы координат для окна (window origin ) установлено в точку (0,0). Для перемещения начала системы координат окна можно использовать функцию SetWindowOrg .
Настройка атрибутов контекста отображения для рисования линий
Настройка атрибутов контекста отображения для рисования линий
Как это нетрудно заметить, функции, предназначенные для рисования линий, не имеют никаких параметров, определяющих толщину, цвет и стиль линии. Эти, а также другие характеристики (например, режим прозрачности), выбираются при установке соответствующих атрибутов контекста отображения.
NCopies
nCopies
Значение для инициализации органа управления "Copies", если поле hDevMode содержит значение NULL.
NFromPage
nFromPage
Начальное значение для инициализации органа управления "From" диалоговой панели "Print". Используется только в том случае, если в поле Flags указан флаг PD_PAGENUMS. Максимальное значение для поля nFromPage составляет 0xfffe.
После возвращения из функции PrintDlg это поле содержит номер страницы документа, с которой должна начинаться печать.
NMaxPage
nMaxPage
Максимальное количество страниц, которое можно задать при помощи органов управления "From" и "To".
NMinPage
nMinPage
Минимальное количество страниц, которое можно задать при помощи органов управления "From" и "To".
NToPage
nToPage
Начальное значение для инициализации органа управления "To" диалоговой панели "Print". Используется только в том случае, если в поле Flags указан флаг PD_PAGENUMS. Максимальное значение для поля nFromPage составляет 0xfffe.
После возвращения из функции PrintDlg это поле содержит номер страницы документа, до которой должна выполняться печать.
Область эллиптической формы
Область эллиптической формы
Область эллиптической формы (или, как частный случай, круглой формы) можно создать при помощи функции CreateEllipticRgn : HRGN WINAPI CreateEllipticRgn( int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
Параметры этой функции описывают координаты воображаемого прямоугольника, в который вписана область эллиптической формы.
Функция CreateEllipticRgnIndirect также используется для создания области в форме эллипса: HRGN WINAPI CreateEllipticRgnIndirect(const RECT FAR* lprc);
В отличие от функции CreateEllipticRgn координаты прямоугольника задаются с помощью структуры типа RECT, указатель на которую передается через параметр lprc.
Область ограничения
Область ограничения
По умолчанию в контексте отображения задана область ограничения вывода (clipping region ), совпадающая со всей областью вывода. Например, если приложение получило контекст отображения для окна, область ограничения совпадает с внутренней областью (client region) этого окна.
Приложение может создавать область ограничения вывода сложной, практически произвольной, формы, исключая или включая в нее области в виде многоугольников или эллипсов. Это позволяет получить при отображении интересные эффекты, труднодостижимые без использования областей ограничения (правда, ценой снижения скорости вывода изображения).
Для работы с областями предназначены следующие функции: CreateEllipticRgn , CreateEllipticRgnIndirect , CreatePolygonRgn , CreatePolyPolygonRgn , CreateRectRgn , CreateRoundRectRgn , ExcludeClipRgn , IntersectClipRgn , OffsetClipRgn , SelectclipRgn .
Область ограничения
Приложение может использовать область для маски, ограничивающей вывод. Для этого область следует выбрать в контекст отображения функцией SelectClipRgn : int WINAPI SelectClipRgn(HDC hdc, HRGN hrgn);
В качестве значения параметра hrgn вы можете использовать значение NULL. В этом случае для ограничения вывода будет использована внутренняя область окна.
Область в виде многоугольника
Область в виде многоугольника
Можно создать область в виде произвольного многоугольника. Для этого следует воспользоваться функцией CreatePolygonRgn : HRGN WINAPI CreatePolygonRgn( const POINT FAR* lppt, // адрес массива точек int cPoints, // размер массива int fnPolyFillMode); // режим заполнения
Функция CreatePolyPolygonRgn создает область, состоящую из нескольких многоугольников: HRGN WINAPI CreatePolyPolygonRgn( const POINT FAR* lppt, // адрес массива точек int FAR* lpnPolyCounts, // адрес массива количества точек // в многоугольниках int cPolygons); // количество многоугольников
Назначение параметров описанных выше двух функций аналогично назначению параметров функций рисования многоугольников Polygon и PolyPolygon (за исключением того, что при создании области не требуется указывать идентификатор контекста отображения).
Общий контекст отображения
Общий контекст отображения
Этот контекст используется чаще всего и поэтому для ускорения доступа к нему Windows использует кеширование (как мы уже говорили, размер кеша достаточен для хранения только пяти контекстов отображения).
Для получения общего контекста отображения приложение должно вызвать функцию BeginPaint (при обработке сообщения WM_PAINT ) или GetDC (при обработке других сообщений). При этом перед регистрацией класса окна в поле стиля класса окна в структуре WNDCLASS не должны использоваться значения CS_OWNDC , CS_PARENTDC или CS_CLASSDC : wc.style = 0;
Функция BeginPaint возвращает контекст отображения для окна hwnd: HDC WINAPI BeginPaint(HWND hwnd, PAINTSTRUCT FAR* lpps);
Перед этим она подготавливает указанное окно для рисования, заполняя структуру типа PAINTSTRUCT (адрес которой передается через параметр lpps) информацией, которую можно использовать в процессе рисования.
Структура PAINTSTRUCT и указатели на нее (различных типов) описаны в файле windows.h: typedef struct tagPAINTSTRUCT { HDC hdc; BOOL fErase; RECT rcPaint; BOOL fRestore; BOOL fIncUpdate; BYTE rgbReserved[16]; } PAINTSTRUCT; typedef PAINTSTRUCT* PPAINTSTRUCT; typedef PAINTSTRUCT NEAR* NPPAINTSTRUCT; typedef PAINTSTRUCT FAR* LPPAINTSTRUCT;
Рассмотрим назначение отдельных полей структуры PAINTSTRUCT.
Поле hdc после возврата из функции будет содержать идентификатор полученного контекста отображения, который должен передаваться в качестве параметра функциям интерфейса GDI, выполняющим рисование. Можно использовать также значение идентификатора контекста, возвращенное функцией BeginPaint, так как эти значения одинаковые.
Анализируя содержимое поля fErase, приложение может определить, нужно ли перерисовывать фон окна. Если в этом поле находится значение TRUE, фон окна должен быть перерисован. Такая необходимость может возникнуть в том случае, если в классе, на базе которого создано окно, при регистрации не была выбрана кисть для закрашивания фона (поле hbrBackground структуры WNDCLASS).
Поле rcPaint, которое представляет собой структуру типа RECT, содержит координаты верхнего левого и правого нижнего угла прямоугольника, внутри которого нужно рисовать. Напомним вам формат структуры RECT , описанной в файле windows.h: typedef struct tagRECT { int left; int top; int right; int bottom; } RECT;
Мы уже говорили вам в 11 томе "Библиотеки системного программиста", что при обработке сообщения WM_PAINT приложение должно суметь перерисовать все окно или любую его часть. Сообщение WM_PAINT может попасть в функцию окна в том случае, если все окно или его часть требуют перерисовки. Поле rcPaint в структуре PAINTSTRUCT содержит координаты прямоугольной области, расположенной в окне и требующей перерисовки.
Остальные поля зарезервированы для Windows и не используются приложениями.
Контекст отображения, полученный при помощи функции BeginPaint, необходимо освободить перед завершением обработки сообщения WM_PAINT, вызвав функцию EndPaint : void WINAPI EndPaint(HWND hwnd, const PAINTSTRUCT FAR* lpps);
Функции EndPaint передаются те же параметры, что и функции BeginPaint.
Обычно обработчик сообщения WM_PAINT выглядит следующим образом: PAINTSTRUCT ps; HDC hdc; ........ case WM_PAINT: { // Получаем контекст отображения hdc = BeginPaint(hwnd, &ps); // После получения контекста отображения // можно вызывать функции GDI TextOut(hdc, 0, 0, (LPSTR)"String", 6); . . // Освобождаем контекст отображения EndPaint(hwnd, &ps); break; }
Подобный фрагмент кода вы можете найти в приложениях, описанных в одном из предыдущих томов "Библиотеки системного программиста".
Функции BeginPaint и EndPaint можно использовать только внутри обработчика сообщения WM_PAINT. Если же приложению требуется рисовать во время обработки других сообщений, оно должно получить контекст отображения с помощью функции GetDC . После завершения процедуры рисования перед выходом из обработчика сообщения следует освободить полученный контекст отображения, вызвав функцию ReleaseDC .
Функция GetDC возвращает контекст отображения для окна с идентификатором hwnd: HDC WINAPI GetDC(HWND hwnd);
Полученный таким образом контекст отображения можно использовать для рисования во внутренней области окна (window client region).
Функция ReleaseDC освобождает контекст отображения hdc, полученный для окна hwnd: int WINAPI ReleaseDC(HWND hwnd, HDC hdc);
Мы еще раз обращаем ваше внимание на необходимость своевременного освобождения общего контекста отображения.
Каждый раз, когда приложение получает общий контекст отображения, его атрибуты принимают значения по умолчанию, перечисленные нами ранее. Если перед выполнением рисования приложение изменит атрибуты контекста отображения, вызвав соответствующие функции GDI, в следующий раз при получении общего контекста отображения эти атрибуты снова примут значения по умолчанию. Поэтому установка атрибутов должна выполняться каждый раз после получения общего контекста отображения. Такая процедура отнимает дополнительное время, но она необходима при использовании контекста отображения этого типа.