Смекни!
smekni.com

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

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

Получение хендла контекста устройства

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

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

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

Существует 7 основных методов получения и освобождения контекста устройства; причем каждый метод создает специфичный контекст устройства, предназначенный для выполнения определенных действий. Надо хорошо представлять, в каком случае каким методом надо пользоваться. Функции BeginPaint, GetDC, GetWindowDC возвращают заранее заготовленный контекст устройства, а функции CreateDC, CreateIC, CreateCompatibleDC и CreateMetaFile создают новый контекст.

1) При обработке сообщения WM_PAINT рекомендуется применять следующий способ:

PAINTSTRUCT ps;

BeginPaint (hWnd, &ps);

...

EndPaint (hWnd, &ps);

Структура PAINTSTRUCT содержит следующие данные:

typedef struct tagPAINTSTRUCT {

HDC hdc; // хендл контекста, он же возвращается функцией BeginPaint

BOOL fErase; // TRUE, если фон неверного прямоугольника надо очищать

RECT rcPaint; // неверный прямоугольник, может быть пустым!

// остальные поля используются Windows:

BOOLfRestore;

BOOL fIncUpdate;

BYTE rgbReserved[ 16 ];

} PAINTSTRUCT;

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

Начиная с Windows 3.x для задания областей, нуждающихся в перерисовке используются не неверные прямоугольники, а неверные области (region), которые могут быть сложной формы. В этом случае прямоугольник rcPaint может быть указан пустым, в то время как неверная область реально существует.

Кроме этого, функция BeginPaint выполняет еще несколько операций:

если fErase равен TRUE, тогда функция BeginPaint вызывает обработку сообщения WM_ERASEBKGND с параметрами wParam= hDC, lParam= 0

неверный прямоугольник маркируется верным. Для этого BeginPaint вызывает функцию ValidateRect.

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

2) Иногда необходимо получить хендл контекста для всей внутренней области окна. Для этого вы можете воспользоваться следующим способом:

HDC hDC;

hDC = GetDC (hWnd);

...

ReleaseDC (hWnd, hDC);

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

восстановление фона окна (так как обычно это делает BeginPaint)

удалите неверные прямоугольники после рисования (так, например, вы можете вызвать ValidateRect (hWnd, NULL); для маркирования всего окна верным).

3) Еще реже приходится рисовать во внешней (неклиентной, non–client) части окна, тогда вы можете воспользоваться таким способом:

HDC hDC;

hDC = GetWindowDC (hWnd);

...

ReleaseDC (hWnd, hDC);

Применяя такой контекст устройства вы можете рисовать, например, на иконке, когда ваше приложение минимизировано.

Интересная особенность этой функции — если в качестве хендла окна ей передать NULL, то функция возвратит хендл контекста, соответствующего всему дисплею.

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

HDChDC;

hDC = CreateDC (lpszDriver, lpszDevice, lpszOutput, lpData);

...

DeleteDC (hDC);

Например, для рисования непосредственно на поверхности дисплея:

hDC = CreateDC ("DISPLAY", NULL, NULL, NULL);

илипринтера:

hDC = CreateDC ("IBMGRX", "IBM Graphics", "LPT1:", NULL);

параметры имеют следующие значения:

lpszDriver — имя драйвера (имя файла без расширения)
lpszDevice — имя устройства (если один драйвер поддерживает несколько устройств)
lpszOutput — имя устройства вывода
lpData — указатель на данные, передаваемые во время инициализации.

Функция CreateDC применяется сравнительно редко, так как первоначально она была ориентирована на работу с устройствами типа принтера или плоттера. Однако, для применения этой функции надо было анализировать информацию об используемом принтере (ах), содержащуюся в файле win.ini. Начиная с Windows 3.x появились специальная библиотека, реализующая стандартные диалоги и наиболее распространенные действия, включая процесс получения контекста принтера. См., например, функцию ChoosePrinter.

5) Иногда получаемый контекст нужен только для того, что бы узнать характеристики устройства. Тогда создается несколько упрощенный, так называемый информационный контекст:

HDC hDC;

hDC = CreateIC (lpszDriver, lpszDevice, lpszOutput, lpData);

...

DeleteDC (hDC);

параметры функции такие же, как и в предыдущем случае.

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

6) Этот способ создает контекст так называемого совместимого устройства, оно реально не существует, но обладает характеристиками реально существующего.

HDC hCompatDC;

HDC hRealDC;

// для получения контекста реального устройства годится любой

// из способов 1..5

hRealDC= GetDC (hWnd);

// по хендлу контекста реально существующего устройства создается

// контекст совместимого устройства.

hCompatDC= CreateCompatibleDC (hRealDC);

// созданный таким образом совместимый контекст описывает устройство

// размером в 1 пиксел. Для нормальной работы с этим устройством

// его надо ассоциировать с битмапом, об этом - позже