Смекни!
smekni.com

Основы графического вывода (стр. 3 из 26)

// если контекст реального устройства нам больше не нужен, мы можем

// его освободить

ReleaseDC (hWnd, hRealDC);

// .. здесь мы можем использовать созданный совместимый контекст

// для освобождения совместимого контекста применяетсяфункция

DeleteDC (hCompatDC);

Совместимые контексты (compatible DC, memory DC) предназначены для работы с битмапами. Для этого созданный совместимый контекст ассоциируется с конкретным битмапом, после чего появляется возможность выполнять рисование на этом битмапе, либо осуществлять передачу изображения между битмапом и другим контекстом устройства. Подробнее о применении совместимых контекстов устройства см. в разделе «Работа с зависимым от устройства битмапом».

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

HDC hDC;

HANDLE hMF;

hDC = CreateMetaFile (lpszFilename);

...

hMF = CloseMetaFile (hDC);

...

DeleteMetaFile (hMF);

или

HDC hEnhDC;

HENHMETAFILE hEnhMF;

hEnhDC = CreateEnhMetaFile (lpszFilename);

...

hEnhMF = CloseEnhMetaFile (hDC);

...

DeleteEnhMetaFile (hEnhMF);

Как использовать полученный хендл метафайла мы рассмотрим позже.

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

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

Сохранение контекста устройства

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

Сохранение контекста может выполняться двумя существенно различающимися путями. Так, если вам надо для выполнения какого–то фрагмента рисунка изменить большое число атрибутов контекста, а для продолжения рисования их надо восстановить, то удобно воспользоваться парой функций SaveDC и RestoreDC для сохранения и восстановления контекста.

HDC SaveDC (hDC);

BOOL RestoreDC (hDC, hSavedDC);

Возможно специальное применение функции RestoreDC (hDC, -1) — восстановить в том виде, какой был перед последним вызовом SaveDC.

Однако простым изменением порядка рисования можно в большинстве случаев обойтись без применения этих функций.

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

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

При работе с окнами, имеющими стиль CS_OWNDC удобно настраивать атрибуты контекста при создании окна, например так:

int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)

{WNDCLASSwc;

// при регистрации класса окна задать стиль CS_OWNDC:

wc.style= CS_OWNDC;...

RegisterClass (&wc);...}

// при обработке сообщений в оконной функции:

LRESULT WINAPI _export WinProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

{HDC hDC;

PAINTSTRUCT ps;

switch (wMsg) {

case WM_CREATE:...

hDC= GetDC (hWnd);

// ... установить атрибуты при создании окна

ReleaseDC (hWnd, hDC);...

break;

case WM_PAINT:

hDC= BeginPaint (hWnd, &ps);

// обычные функции получения хендла контекста устройства будут теперь

// возвращать хендл сохраненного контекста.

// здесь используются атрибуты, установленные ранее...

EndPaint (hWnd, &ps); // контекст по-прежнему должен быть освобожден

break;

case ...:...}

...}

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

В частном случае все окна одного класса могут иметь одинаковые атрибуты. Тогда можно указать стиль не CS_OWNDC, а CS_CLASSDC. Этот стиль указывает на то, что используется только одна сохраненная копия контекста в памяти, которая используется всеми окнами данного класса. В этом случае можно настраивать атрибуты контекста еще в функции WinMain, сразу после создания первого окна этого класса.

Системы координат GDI

Для начала надо уточнить то место, которое занимает система координат GDI в Windows. Как отмечалось при первом знакомстве, в Windows используется одновременно несколько разных систем координат. Среди них надо выделить следующие:

Система координат менеджера окон; в документации никак особо не оговаривается, что применяется именно эта система координат.

Система координат панели диалога; применяется только при разработке собственных диалогов. В тексте часто можно понять, что речь идет именно о ней, если оговаривается, что используются единицы диалога (dialog units). Если не оговаривается, то по контексту — все, связанное с шаблонами и ресурсами описания диалогов использует именно эту систему отсчета.

Система координат GDI; в документации координаты в системе координат GDI часто называют логическими координатами (logical coordinates). Там же может встретиться понятие координаты устройства (device coordinates).

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

Основные понятия

Вообще говоря, для задания любой системы координат необходимо как–то ее привязать к системе координат устройства (речь идет о системах координат, применяемых в Windows, а не о математическом понятии). Так, скажем, система координат менеджера окон отличается от системы координат устройства только лишь смещенным (а возможно и нет) началом отсчета — в верхний левый угол внутренней области окна.

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

В любом случае в Windows ту систему координат, по отношению к которой задается система координат GDI, называют системой координат устройства (device coordinates, viewportcoordinates). А саму систему координат GDI называют логической системой координат (logical coordinates, window coordinates).

Обратите внимание, что английская терминология в этой области очень путаная, одно и то же понятие может обозначаться разными терминами даже в пределах одного абзаца. Так, термины viewport и device относятся к системе координат устройства, а термины logical и window описывают логическую систему координат. Это несколько странно, так как при выводе в окно система координат окна будет соответствовать координатам устройства, а логические координаты, используемые GDI, почему–то будут обозначаться термином window.

Когда система предоставляет вам контекст устройства, то его система координат совпадает с координатами устройства (окна), но у вас есть возможность эту систему координат самостоятельно изменить во время рисования на контексте.

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


В этих формулах используются нижние индексы в виде view и win, в соответствии с принятыми названиями атрибутов контекста устройства. Индекс view относится к системе координат устройства, а индекс win — к логической системе координат. То есть xview и yview — координаты какой–либо точки в системе координат устройства, Xview.org и Yview.org— относительное смещение начал отсчета систем координат, выраженное в единицах устройства (viewport origin), Xwin.org и Ywin.org — то же самое смещение, но выраженное в логических единицах (window origin), а Xview.ext, Yview.ext и Xwin.ext, Ywin.ext— масштабные коэффициенты (viewport extents, window extents).

Естественно, что в этих формулах смещение начала отсчета должно задаваться лишь единожды — либо для логической системы координат, либо для системы координат устройства. В каком именно виде — зависит исключительно от удобства. Например, если вы хотите начало отсчета логической системы координат поместить точно в центре окна (листа бумаги и пр.), то фактически вы знаете положение точки начала отсчета в координатах устройства — размеры контекста устройства, деленные пополам — тогда удобнее задать величины Xview.org и Yview.org, а Xwin.org и Ywin.org оставить равными нулю.