Смекни!
smekni.com

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

red_brick BITMAP rbrick.bmp

1 BITMAP firm.bmp

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

Для загрузки битмапа из ресурсов приложения используются функции:

HBITMAP LoadBitmap (hInstance, lpszName);

HANDLE LoadImage (hInstance, lpszName, uType, cxDesired, cyDesired, fuLoad); 1

где hInstance — хендл копии приложения, содержащего данный битмап, а lpszName — имя ресурса битмапа. Имя ресурса может быть либо текстом — тогда lpszName это обычная строка, оканчивающаяся символом ‘\0’, либо номером — тогда вместо lpszName может стоять или «#number», или MAKEINTRESOURCE (number). Например, для загрузки битмапов «red_brick» и «1» можно воспользоваться такими вызовами функций:

HBITMAP hbmpRedBrick = LoadBitmap (hInstance, "red_brick");

HBITMAP hbmp1a = LoadBitmap (hInstance, "#1");

HBITMAP hbmp1b = LoadBitmap (hInstance, MAKEINTRESOURCE (1));

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

Функция LoadImage осуществляет загрузку битмапов, пиктограмм и курсоров. Теоретически она позволяет загружать требуемый ресурс из файла (для этого в fuLoad надо установить флаг LR_LOADFROMFILE и указать hInstance равным NULL). Однако такая операция поддерживается только в случае Windows–95, WindowsNT 4.0 и более поздних. Предыдущие реализации Win32 API не поддерживают загрузку изображений из файлов.

Вы можете использовать стандартные битмапы, предоставляемые Windows. Их символические имена начинаются на OBM_... . Для того, что бы вы могли воспользоваться этими идентификаторами, необходимо перед директивой #include <windows.h> определить символ OEMRESOURCE, то есть:

#define OEMRESOURCE

#include <windows.h>

В таблице приведены изображения стандартных битмапов и их идентификаторы, в соответствии с их реализацией в Windows 3.x (Windows API) и Windows NT 3.x (Win32 API); в более поздних версиях (как, например, Windows–95, Windows NT 4.0) внешний вид стандартных битмапов несколько изменен. В таблице заполнены не все клетки просто из соображений построчной группировки схожих битмапов.

OBM_UPARROW
OBM_UPARROWI
OBM_UPARROWD
OBM_OLD_UPARROW
OBM_DNARROW
OBM_DNARROWI
OBM_DNARROWD
OBM_OLD_DNARROW
OBM_RGARROW
OBM_RGARROWI
OBM_RGARROWD
OBM_OLD_RGARROW
OBM_LFARROW
OBM_LFARROWI
OBM_LFARROWD
OBM_OLD_LFARROW
OBM_REDUCE
OBM_REDUCED
OBM_OLD_REDUCE
OBM_ZOOM
OBM_ZOOMD
OBM_OLD_ZOOM
OBM_RESTORE
OBM_RESTORED
OBM_OLD_RESTORE
OBM_CLOSE
OBM_OLD_CLOSE
OBM_MNARROW
OBM_COMBO
OBM_SIZE
OBM_BTSIZE
OBM_CHECK
OBM_BTNCORNERS
OBM_CHECKBOX

Работа с зависимым от устройства битмапом

Небольшое замечание: так как битмап является объектом GDI, то вы обязаны удалить его, как только он станет ненужным. Это относится ко всем битмапам, как созданным с помощью функций CreateBitmap, CreateBitmapIndirect, CreateCompatibleBitmap, CreateDiscardableBitmap, так и к загруженным с помощью функции LoadBitmap. Освобождение неиспользуемых битмапов особенно важно, так как это едва–ли не самые большие объекты GDI, занимающие значительные ресурсы.

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

HBRUSH hbrBrush = CreatePatternBrush (hBmp);

DeleteBitmap (hBmp); // 2

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

Все остальные операции по работе с битмапами осуществляются посредством специально создаваемого контекста устройства, ассоциированного с этим битмапом. Для этого был разработан специальный вид контекстов устройства — совместимый контекст (compatible device context, compatible DC, чаще называемый memory device context, memory DC). Такой разнобой в названиях контекста связан, с одной стороны, с названием функции, его создающей — CreateCompatibleDC — создающей контекст устройства, совместимого с другим, реально существующим устройством (см. раздел «Получение хендла контекста устройства»). А, с другой стороны, созданный таким образом контекст устройства не соответствует никакому физическому устройству, его область отображения — некоторое растровое изображение, хранимое в памяти. Отсюда второе название — memory DC.

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

Только что созданный совместимый контекст устройства имеет монохромную область отображения размером 1 пиксель. Так как нарисовать что–нибудь осмысленное в такой области нереально, вы должны принять меры к тому, что бы область отображения этого контекста была ассоциирована с хранимым в памяти растровым изображением — зависимым от устройства битмапом. Это делается тривиально — битмап выбирается в совместимый контекст устройства с помощью обычной функции SelectObject. После этого область отображения совместимого контекста будет совпадать с указанным битмапом — как по размерам, так и по цветовой организации.

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

Общая схема при этом выглядит следующим способом:

HDC hCompatDC;

HBITMAP hBmp;

hCompatDC = CreateCompatibleDC (hDC);

// функция CreateCompatibleDC () создает совместимый

// контекст устройства, соответствующий одному монохромному пикселу

hBmp = LoadBitmap (hInstance, lpszName);

// для получения хендла битмапа мы могли воспользоваться любым

// способом - его загрузкой из ресурсов или созданием

SelectObject (hCompatDC, hBmp);

// теперь совместимый контекст устройства соответствует нашему битмапу.

// ... здесь мы можем выполнять любые операции по рисованию на нашем битмапе

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

DeleteDC (hCompatDC);

// после того, как мы выполнили все нужные операции над контекстом

// устройства, мы можем его удалить.

// ... При этом битмап как объект GDI остается и мы можем свободно

// ... применять его хендл. Например, для создания кисти, или для

// ... отображения пункта меню.

DeleteObject (hBmp);

// после того, как битмап стал нам не нужен, мы можем его уничтожить

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