Графический интерфейс GDI в Microsoft Windows
5b239685

Приложение BMPINFO


После всего сказанного выше у вас могло сложиться впечатление, что процедура рисования изображений DIB значительно труднее, чем процедура рисования файлов DDB. В самом деле, для отображения содержимого bmp-файла вы должны считать его в память, проверить формат всех структур, при необходимости создать палитру и следить за ее изменениями со стороны других приложений. В момент рисования вам нужно подготовить значительное количество структур, указателей и параметров. Увы, для рисования изображений DIB в программном интерфейсе GDI операционной системы Windows версии 3.1 нет ничего более удобного, чем описанные нами функции.

Большинство приложений, тем не менее, нуждается в рисовании изображений DIB. Для иллюстрации методов работы с такими изображениями мы подготовили приложение BMPINFO. Это приложение умеет загружать bmp-файлы любых "легальных" форматов Windows и Presentation Manager версии 1.x, и выводит соответствующую информацию из заголовков этих файлов, однако оно способно рисовать только некомпрессованные изображения в формате Windows. Как мы уже говорили, в большинстве случаев это как раз именно то, что нужно.

В меню "File" есть строки "Open", "Info..." и, конечно, "Exit". С помощью строки "Open" вы можете выбрать bmp-файл. Если это некомпрессованный файл в формате Windows, он рисуется в окне приложения (рис. 4.7).

Рис. 4.7. Главное окно приложения BMPINFO

Выбрав из меню "File" строку "Info...", вы можете просмотреть информацию о файле, такую, как размер файла и заголовка, формат файла, размер изображения в пикселах и т. д. (рис. 4.8).

Рис. 4.8. Информация о bmp-файле

Если выбранный bmp-файл имеет формат Presentation Manager, на экране появится диалоговая панель, аналогичная изображенной на рис. 4.8.

Основной файл исходных текстов приложения BMPINFO приведен в листинге 4.6.

Листинг 4.6. Файл bmpinfo/bmpinfo.cpp

// ---------------------------------------- // Приложение BMPINFO // Просмотр и анализ bmp-файлов в формате DIB // ----------------------------------------




#define STRICT #include <windows.h> #include <windowsx.h> #include <commdlg.h> #include <mem.h> #pragma hdrstop

#include "dib.hpp" #include "bmpinfo.hpp"

// Прототипы функций BOOL InitApp(HINSTANCE); LRESULT CALLBACK _export WndProc(HWND, UINT, WPARAM, LPARAM);

// Имя класса окна char const szClassName[] = "BmpInfoClass";

// Заголовок окна char const szWindowTitle[] = "Bitmap Information";

// Размеры внутренней области окна short cxClient, cyClient;

// ===================================== // Функция WinMain // ===================================== #pragma argsused

int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { MSG msg; // структура для работы с сообщениями HWND hwnd; // идентификатор главного окна приложения

// Инициализируем приложение if(!InitApp(hInstance)) return FALSE;

// После успешной инициализации приложения создаем // главное окно приложения hwnd = CreateWindow( szClassName, // имя класса окна szWindowTitle, // заголовок окна WS_OVERLAPPEDWINDOW, // стиль окна CW_USEDEFAULT, // задаем размеры и расположение CW_USEDEFAULT, // окна, принятые по умолчанию CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, NULL);

// Если создать окно не удалось, завершаем приложение if(!hwnd) return FALSE;

// Рисуем главное окно ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd);

// Запускаем цикл обработки сообщений while(GetMessage(&msg, 0, 0, 0)) { DispatchMessage(&msg); } return msg.wParam; }

// ===================================== // Функция InitApp // Выполняет регистрацию класса окна // =====================================

BOOL InitApp(HINSTANCE hInstance) { ATOM aWndClass; // атом для кода возврата WNDCLASS wc; // структура для регистрации // класса окна // Записываем во все поля структуры нулевые значения memset(&wc, 0, sizeof(wc));

// Подключаем меню wc.lpszMenuName = "APP_MENU";

wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH); wc.lpszClassName = (LPSTR)szClassName;



// Регистрация класса aWndClass = RegisterClass(&wc);

return (aWndClass != 0); }

// ===================================== // Функция WndProc // =====================================

LRESULT CALLBACK _export WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps;

static HFILE hfDIBFile; static HDIB hDib; static HPALETTE hPal, hOldPal;

// Размер файла static DWORD dwFileSize;

switch (msg) { case WM_CREATE: { hfDIBFile = NULL; hDib = NULL; hPal = NULL; return 0; }

// При изменении размеров окна сохраняем // новые значения для ширины и высоты case WM_SIZE: { cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); return 0; }

// Рисование в окне case WM_PAINT: { // Получаем контекст отображения для // рисования во внутренней области окна hdc = BeginPaint(hwnd, &ps);

// Если DIB был загружен, и он в формате // некомпрессованного bmp-файла для Windows, // рисуем его if((hDib != NULL) && (DIBType(hDib) == WINRGB_DIB)) { // Если при загрузке была создана палитра, // выбираем ее if(hPal) { hOldPal = SelectPalette(hdc, hPal, FALSE); RealizePalette(hdc); }

// Рисуем DIB DIBPaint(hdc, 0, 0, hDib);

// Выбираем старую палитру if(hPal) { SelectPalette(hdc, hOldPal, FALSE); } }

// Для других форматов bmp-файлов выводим // информацию из заголовка файла else { if(hDib) DIBInfo(hDib, dwFileSize); }

// Освобождаем контекст отображения EndPaint(hwnd, &ps); return 0; }

// Обработка сообщений от меню case WM_COMMAND: { switch (wParam) { case CM_HELPABOUT: { MessageBox(hwnd, "Bitmap Information, v.1.0\n" "(C) Frolov A.V., 1994", "About BMPINFO", MB_OK | MB_ICONINFORMATION); return 0; }

// Загрузка bmp-файла case CM_FILEOPEN: { // Выбираем файл hfDIBFile = DIBSelectFile();

if(hfDIBFile != NULL) { // Читаем файл в память hDib = DIBReadFile(hfDIBFile, &dwFileSize);

// Если файл прочитан, создаем палитру на // базе таблицы цветов. Если таблицы цветов нет, // палитра не создается if((hDib != NULL) && (DIBType(hDib) == WINRGB_DIB)) { hPal = DIBCreatePalette(hDib); }



// Перерисовываем окно InvalidateRect(hwnd, NULL, TRUE); } return 0; }

// Выводим диалоговую панель с информацией из // заголовка bmp-файла case CM_FILEINFO: { if(hDib != NULL) DIBInfo(hDib, dwFileSize);

return 0; }

// Завершаем работу приложения case CM_FILEEXIT: { DestroyWindow(hwnd); return 0; }

default: return 0; } }

// Это сообщение приходит при изменении // системной палитры. Наше приложение в ответ // на это сообщение заново реализует свою логическую // палитру и при необходимости перерисовывает окно case WM_PALETTECHANGED: { // Если это не наше окно, передаем управление // обработчику сообщения WM_QUERYNEWPALETTE if (hwnd == (HWND) wParam) break; }

// В ответ на это сообщение приложение должно // реализовать свою логическую палитру и // обновить окно case WM_QUERYNEWPALETTE: { HDC hdc; HPALETTE hOldPal; int nChanged;

// Выбираем логическую палитру в // контекст отображения hdc = GetDC(hwnd);

// При обработке сообщения WM_QUERYNEWPALETTE // палитра выбирается для активного окна, // а при обработке сообщения WM_PALETTECHANGED - // для фонового hOldPal = SelectPalette(hdc, hPal, (msg == WM_QUERYNEWPALETTE) ? FALSE : TRUE);

// Реализуем логическую палитру и выбираем // ее в контекст отображения nChanged = RealizePalette(hdc); SelectPalette(hdc, hOldPal, TRUE);

// Освобождаем контекст отображения ReleaseDC(hwnd, hdc);

// Если были изменения палитры, // перерисовываем окно if(nChanged) InvalidateRect(hwnd, NULL, TRUE);

return nChanged; }

case WM_DESTROY: {

// Удаляем логическую палитру

if(hPal)

DeletePalette(hPal);

PostQuitMessage(0); return 0; }

default: break; } return DefWindowProc(hwnd, msg, wParam, lParam); }

Обработчик сообщения WM_CREATE сбрасывает содержимое переменных, в которых находятся идентификатор открытого bmp-файла, идентификатор загруженного изображения DIB, а также идентификатор палитры:

hfDIBFile = NULL; hDib = NULL; hPal = NULL;

Обработчик сообщения WM_PAINT, рисующий изображение DIB, достаточно прост:

hdc = BeginPaint(hwnd, &ps); if((hDib != NULL) && (DIBType(hDib) == WINRGB_DIB)) { if(hPal) { hOldPal = SelectPalette(hdc, hPal, FALSE); RealizePalette(hdc); } DIBPaint(hdc, 0, 0, hDib); if(hPal) { SelectPalette(hdc, hOldPal, FALSE); } } else { if(hDib) DIBInfo(hDib, dwFileSize); } EndPaint(hwnd, &ps); return 0;



Если загружено изображение DIB, его идентификатор отличен от NULL. В этом случае вызывается функция DIBType, определенная в нашем приложении в файле dib.cpp (листинг 4.8). Эта функция выполняет все необходимые проверки полей структуры заголовка изображения и возвращает тип изображения. Для некомпрессованных изображений DIB в формате Windows возвращается значение WINRGB_DIB.

Если при загрузке bmp-файла выяснилось, что он содержит таблицу цветов, создается палитра, идентификатор которой записывается в переменную hPal. Если содержимое этой переменной отлично от NULL, перед рисованием обработчик сообщения WM_PAINT выбирает палитру в контекст отображения и реализует ее, вызывая функции SelectPalette и RealizePalette.

Далее вызывается функция DIBPaint, определенная в файле dib.cpp, которая рисует изображение DIB. В качестве параметров этой функции передается идентификатор контекста отображения, координаты (x,y) левого верхнего угла прямоугольной области, в которой нужно нарисовать изображение, и идентификатор загруженного изображения DIB.

После этого восстанавливается старая палитра (если были изменения палитры).

Если же было загружено изображение DIB в формате Presentation Manager, вызывается функция DIBInfo, которая выводит на экран диалоговую панель с параметрами этого изображения.

При выборе в меню "File" строки "Open" получает управление обработчик сообщения WM_COMMAND. Этот обработчик вызывает функцию DIBSelectFile, определенную в файле dib.cpp. Функция DIBSelectFile выводит на экран стандартную диалоговую панель "Open" и позволяет вам выбрать для загрузки любой файл. Идентификатор открытого файла записывается в переменную hfDIBFile.

Далее файл читается в память, для чего вызывается функция DIBReadFile, определенная в файле dib.cpp. Функция читает весь файл в заказанный ей глобальный блок памяти, причем перед возвратом управления отмечает этот блок как перемещаемый и возвращает идентификатор блока памяти. Дополнительно она записывает размер файла в байтах в переменную, адрес которой указан ей в качестве второго параметра.



После удачного чтения с помощью функции DIBType определяется тип файла. Если это некомпрессованный файл в формате Windows, вызывается функция DIBCreatePalette, которая проверяет наличие таблицы цветов и при необходимости создает логическую палитру, записывая ее идентификатор в переменную hPal.

Затем для перерисовки окна и отображения загруженного изображения вызывается функция InvalidateRect.

Обработчики сообщений об изменении системной палитры WM_PALETTECHANGED и WM_QUERYNEWPALETTE аналогичны использованным в приложении PALETTE, поэтому мы не будем их описывать еще раз.

Перед завершением работы приложения функция окна удаляет логическую палитру, если она была создана, вызывая макрокоманду DeletePalette.

Идентификаторы строк меню описаны в файле bmpihfo.hpp (листинг 4.7).

Листинг 4.7. Файл bmpinfo/bmpinfo.hpp

#define CM_HELPABOUT 301 #define CM_FILEOPEN 302 #define CM_FILEINFO 303 #define CM_FILEEXIT 304

Все функции, предназначенные для работы с bmp-файлами и изображениями DIB, загруженными в оперативную память, мы вынесли в отдельный файл dib.cpp (листинг4.8).

Листинг 4.8. Файл bmpinfo/dib.cpp

// ----------------------------------------------------- // Функции для работы с файлами в формате DIB // -----------------------------------------------------

#define STRICT #include <windows.h> #include <windowsx.h> #include <commdlg.h> #include <mem.h> #pragma hdrstop

#include "dib.hpp"

// ------------------------------- // Функция DIBSelectFile // Выбор DIB-файла // -------------------------------

HFILE DIBSelectFile(void) { // Структура для выбора файла OPENFILENAME ofn;

// Буфер для записи пути к выбранному файлу char szFile[256];

// Буфер для записи имени выбранного файла char szFileTitle[256];

// Фильтр расширений имени файлов char szFilter[256] = "Bitmap Files\0*.bmp;*.dib;*.rle\0Any Files\0*.*\0";

// Идентификатор открываемого файла HFILE hf;

// Инициализация имени выбираемого файла // не нужна, поэтому создаем пустую строку szFile[0] = '\0';



// Записываем нулевые значения во все поля // структуры, которая будет использована для // выбора файла memset(&ofn, 0, sizeof(OPENFILENAME));

// Инициализируем нужные нам поля

// Размер структуры ofn.lStructSize = sizeof(OPENFILENAME);

// Идентификатор окна ofn.hwndOwner = NULL;

// Адрес строки фильтра ofn.lpstrFilter = szFilter;

// Номер позиции выбора ofn.nFilterIndex = 1;

// Адрес буфера для записи пути // выбранного файла ofn.lpstrFile = szFile;

// Размер буфера для записи пути // выбранного файла ofn.nMaxFile = sizeof(szFile);

// Адрес буфера для записи имени // выбранного файла ofn.lpstrFileTitle = szFileTitle;

// Размер буфера для записи имени // выбранного файла ofn.nMaxFileTitle = sizeof(szFileTitle);

// В качестве начального каталога для // поиска выбираем текущий каталог ofn.lpstrInitialDir = NULL;

// Определяем режимы выбора файла ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; // Выбираем входной файл if (GetOpenFileName(&ofn)) {

// Открываем выбранный файл hf = _lopen(ofn.lpstrFile, OF_READ);

// Возвращаем идентификатор файла return hf; } // При отказе от выбора возвращаем // нулевое значение else return 0; }

// ------------------------------- // Функция DIBReadFile // Чтение DIB-файла // -------------------------------

HDIB DIBReadFile(HFILE hfDIBFile, DWORD *dwFileSize) { // Идентификатор глобального блока // памяти, который будет использован для // чтения файла HDIB hDib;

HCURSOR hCursor; // идентификатор курсора

// Указатель на глобальный блок памяти LPDIB lpBuf;

// Курсор в виде песочных часов hCursor = SetCursor (LoadCursor(NULL, IDC_WAIT));

// Определяем размер файла. Для этого // устанавливаем текущую позицию на // конец файла *dwFileSize = _llseek(hfDIBFile, 0l, 2);

// Устанавливаем текущую позицию // на начало файла _llseek(hfDIBFile, 0l, 0);

// Заказываем глобальный блок памяти, // размер которого равен длине файла hDib = (HDIB)GlobalAlloc(GMEM_FIXED, *dwFileSize); lpBuf = (unsigned char huge *)GlobalLock(hDib);



// Если мало свободной памяти, // возвращаем признак ошибки if(lpBuf == NULL) return(NULL);

// Читаем файл в полученный блок памяти _hread(hfDIBFile, lpBuf, *dwFileSize);

// Восстанавливаем курсор SetCursor (hCursor);

// Расфиксируем память GlobalUnlock(hDib);

// Закрываем файл _lclose(hfDIBFile);

return hDib; }

// ------------------------------- // Функция DIBInfo // Вывод диалоговой панели с информацией // о DIB-файле // -------------------------------

BOOL DIBInfo(HDIB hDib, DWORD dwFileSize) { char szBuf[256], szBuf1[256]; DWORD biSize; LPBITMAPFILEHEADER lpDIBFileHeader; LPBITMAPINFOHEADER lpDIBInfoHeader; LPBITMAPCOREHEADER lpDIBCoreHeader; DWORD bfOffset; BOOL bWDIB; LPDIB lpDIBPtr; int nDIBType; WORD wNumColors;

// Определяем тип битового изображения nDIBType = DIBType(hDib);

if(!nDIBType) // если ошибка, выдаем сообщение { MessageBox(NULL, "Ошибка в формате DIB-файла", "Bitmap Info", MB_OK | MB_ICONHAND); return FALSE; }

// Фиксируем область памяти, в которую загружен DIB lpDIBPtr = (unsigned char huge *)GlobalLock(hDib); if(lpDIBPtr == NULL) return(FALSE);

lpDIBFileHeader = (LPBITMAPFILEHEADER)lpDIBPtr;

// Определяем смещение бит изображения // и размер заголовка bfOffset = lpDIBFileHeader->bfOffBits; biSize = (DWORD)(lpDIBPtr[sizeof(BITMAPFILEHEADER)]);

// Готовим текстовую строку для вывода wsprintf(szBuf, "Размер заголовка, байт:\t%ld\n", biSize); wsprintf(szBuf1, "Размер файла, байт: \t%ld\n", dwFileSize); lstrcat(szBuf, szBuf1); wsprintf(szBuf1, "Смещение изображения, байт:\t%ld\n", bfOffset); lstrcat(szBuf, szBuf1);

// В зависимости от формата DIB (PM или Windows) // выводим различную информацию из заголовка файла if((nDIBType == WINRGB_DIB) (nDIBType == WINRLE4_DIB) (nDIBType == WINRLE8_DIB)) { wsprintf(szBuf1, "\nBMP для Windows\n", biSize); lstrcat(szBuf, szBuf1); lpDIBInfoHeader = (LPBITMAPINFOHEADER)(lpDIBPtr + sizeof(BITMAPFILEHEADER));

wsprintf(szBuf1, "Размер:\t%ldx%ld\n", lpDIBInfoHeader->biWidth, lpDIBInfoHeader->biHeight); lstrcat(szBuf, szBuf1);



wsprintf(szBuf1, "Бит на пиксел:\t%d\n", lpDIBInfoHeader->biBitCount); lstrcat(szBuf, szBuf1);

wNumColors = DIBNumColors(lpDIBPtr); wsprintf(szBuf1, "Таблица цветов:\t%d\n", wNumColors); lstrcat(szBuf, szBuf1);

if(lpDIBInfoHeader->biCompression == BI_RGB) { lstrcat(szBuf, "Без компрессии\n"); } else if(lpDIBInfoHeader->biCompression == BI_RLE4) { lstrcat(szBuf, "Компрессия RLE4\n"); } else if(lpDIBInfoHeader->biCompression == BI_RLE8) { lstrcat(szBuf, "Компрессия RLE8\n"); } }

// Для файлов DIB в формате PM else { wsprintf(szBuf1, "\nBMP для Presentation Manager\n", biSize); lstrcat(szBuf, szBuf1); lpDIBCoreHeader = (LPBITMAPCOREHEADER)(lpDIBPtr + sizeof(BITMAPFILEHEADER));

wsprintf(szBuf1, "Размер:\t%dx%d\n", lpDIBCoreHeader->bcWidth, lpDIBCoreHeader->bcHeight); lstrcat(szBuf, szBuf1);

wsprintf(szBuf1, "Бит на пиксел:\t%d\n", lpDIBCoreHeader->bcBitCount); lstrcat(szBuf, szBuf1); }

MessageBox(NULL, (LPSTR)szBuf, "Bitmap Info", MB_OK | MB_ICONINFORMATION);

GlobalUnlock(hDib); return TRUE; }

// ------------------------------- // Функция DIBType // Определение и проверка формата DIB // -------------------------------

int DIBType(HDIB hDib) { LPBITMAPFILEHEADER lpDIBFileHeader; LPBITMAPINFOHEADER lpih; LPBITMAPCOREHEADER lpch;

DWORD biSize; LPDIB hDIBPtr; int nDIBType;

if(hDib == NULL) // Неправильный идентификатор DIB return(-2);

// Фиксируем память, в которой находится DIB hDIBPtr = (LPDIB)GlobalLock(hDib); if(hDIBPtr == NULL) return(-1);

lpDIBFileHeader = (LPBITMAPFILEHEADER)hDIBPtr;

// Проверяем тип файла if(lpDIBFileHeader->bfType != 0x4d42) { GlobalUnlock(hDib); return 0; }

// Проверяем размер заголовка biSize = (DWORD)(hDIBPtr[sizeof(BITMAPFILEHEADER)]);

if(biSize == sizeof(BITMAPINFOHEADER)) // 40 байт { // Это заголовок DIB в формате Windows lpih = (LPBITMAPINFOHEADER)(hDIBPtr + sizeof(BITMAPFILEHEADER));

// Проверяем основные поля заголовка DIB if((lpih->biPlanes == 1) && ((lpih->biBitCount == 1) (lpih->biBitCount == 4) (lpih->biBitCount == 8) (lpih->biBitCount == 24)) && ((lpih->biCompression == BI_RGB) (lpih->biCompression == BI_RLE4 && lpih->biBitCount == 4) (lpih->biCompression == BI_RLE8 && lpih->biBitCount == 8))) { // Определяем метод компрессии файла if(lpih->biCompression == BI_RGB) nDIBType = WINRGB_DIB; else if(lpih->biCompression == BI_RLE4) nDIBType = WINRLE4_DIB; else if(lpih->biCompression == BI_RLE8) nDIBType = WINRLE8_DIB; else nDIBType = 0; } else nDIBType = 0; }



else if(biSize == sizeof(BITMAPCOREHEADER)) // 12 байт { // Это заголовок DIB в формате Presentation Manager lpch = (LPBITMAPCOREHEADER)(hDIBPtr + sizeof(BITMAPFILEHEADER));

// Проверяем основные поля заголовка DIB if((lpch->bcPlanes == 1) && (lpch->bcBitCount == 1 lpch->bcBitCount == 4 lpch->bcBitCount == 8 lpch->bcBitCount == 24)) { nDIBType = PM_DIB; } else nDIBType = 0; }

else nDIBType = 0;

GlobalUnlock(hDib);

// Возвращаем тип файла или признак ошибки return nDIBType; }

// ------------------------------- // Функция DIBNumColors // Определение размера палитры // -------------------------------

WORD DIBNumColors(LPDIB lpDib) { DWORD dwColorUsed; LPBITMAPINFOHEADER lpih;

lpih = (LPBITMAPINFOHEADER)(lpDib + sizeof(BITMAPFILEHEADER));

// Количество цветов dwColorUsed = lpih->biClrUsed;

// Если используется палитра уменьшенного размера, // возвращаем нужный размер if(dwColorUsed) return((WORD)dwColorUsed);

// Если количество использованных цветов не указано, // вычисляем стандартный размер палитры исходя из // количества бит, определяющих цвет пиксела switch(lpih->biBitCount) { case 1: return 2; case 4: return 16; case 8: return 256; default: return 0; // палитра не используется } }

// ------------------------------- // Функция DIBHeight // Определение высоты DIB в пикселах // -------------------------------

WORD DIBHeight(LPDIB lpDib) { LPBITMAPINFOHEADER lpih;

lpih = (LPBITMAPINFOHEADER)(lpDib + sizeof(BITMAPFILEHEADER)); return lpih->biHeight; }

// ------------------------------- // Функция DIBWidth // Определение ширины DIB в пикселах // -------------------------------

WORD DIBWidth(LPDIB lpDib) { LPBITMAPINFOHEADER lpih;

lpih = (LPBITMAPINFOHEADER)(lpDib + sizeof(BITMAPFILEHEADER)); return lpih->biWidth; }

// ------------------------------- // Функция DIBFindBits // Определение адреса массива бит изображения // -------------------------------

LPSTR DIBFindBits(LPDIB lpDib) { LPBITMAPFILEHEADER lpfh; LPBITMAPINFOHEADER lpih;



lpfh = (LPBITMAPFILEHEADER)lpDib;

// Используем значение, указанное в заголовке // файла ( если оно не равно нулю) if(lpfh->bfOffBits) return((LPSTR)lpfh + lpfh->bfOffBits);

// Вычисляем адрес исходя из размеров заголовков и // таблицы цветов lpih = (LPBITMAPINFOHEADER)(lpDib + sizeof(BITMAPFILEHEADER));

return((LPSTR)lpih + lpih->biSize + (DWORD)(DIBNumColors(lpDib) * sizeof(RGBQUAD))); }

// ------------------------------- // Функция DIBPaint // Рисование DIB при помощи функции StretchDIBits // -------------------------------

BOOL DIBPaint(HDC hdc, int x, int y, HDIB hDib) { HBITMAP hbmp; HDC hMemDC; WORD wHeight, wWidth; LPDIB lpDib; LPBITMAPINFOHEADER lpih;

lpDib = (LPDIB)GlobalLock(hDib); if(lpDib == NULL) return(-1);

lpih = (LPBITMAPINFOHEADER)(lpDib + sizeof(BITMAPFILEHEADER));

// Определяем размеры DIB wHeight = lpih->biHeight; wWidth = lpih->biWidth;

// Рисуем DIB без масштабирования StretchDIBits(hdc, x, y, wWidth, wHeight, 0, 0, wWidth, wHeight, DIBFindBits(lpDib), (LPBITMAPINFO)lpih, DIB_RGB_COLORS, SRCCOPY);

GlobalUnlock(hDib);

return TRUE; }

// ------------------------------- // Функция DIBPaintBlt // Рисование DIB при помощи функции BitBlt // -------------------------------

BOOL DIBPaintBlt(HDC hdc, int x, int y, HDIB hDib) { HBITMAP hbmp; HDC hMemDC; WORD wHeight, wWidth; LPDIB lpDib; LPBITMAPINFOHEADER lpih;

lpDib = (LPDIB)GlobalLock(hDib); if(lpDib == NULL) return(-1);

lpih = (LPBITMAPINFOHEADER)(lpDib + sizeof(BITMAPFILEHEADER));

wHeight = lpih->biHeight; wWidth = lpih->biWidth;

// Создаем совместимое битовое изображение hbmp = CreateCompatibleBitmap(hdc, wWidth, wHeight);

// Создаем совместимый контекст памяти hMemDC = CreateCompatibleDC(hdc);

// Преобразуем DIB в DDB SetDIBits(hdc, hbmp, 0, wHeight, DIBFindBits(lpDib), (LPBITMAPINFO)lpih, DIB_RGB_COLORS);

// Выбираем DDB в контекст отображения hbmp = (HBITMAP)SelectObject(hMemDC, hbmp);

// Рисуем DDB BitBlt(hdc, x, y, wWidth, wHeight, hMemDC, 0, 0, SRCCOPY);



// Удаляем контекст памяти DeleteObject(SelectObject(hMemDC, hbmp)); DeleteDC(hMemDC);

GlobalUnlock(hDib); return TRUE; }

// ------------------------------- // Функция DIBCreatePalette // Создаем палитру на базе таблицы цветов DIB // -------------------------------

HPALETTE DIBCreatePalette(HDIB hDib) { LPLOGPALETTE lpPal; HPALETTE hPal = NULL; HANDLE hLogPal; int i, wNumColors; LPSTR lpbi; LPBITMAPINFO lpbmi;

if (!hDib) return NULL;

lpbi = (LPSTR)GlobalLock(hDib); lpbmi = (LPBITMAPINFO)(lpbi + sizeof(BITMAPFILEHEADER));

// Определяем размер таблицы цветов wNumColors = DIBNumColors(lpbi);

// Если в DIB есть таблица цветов, создаем палитру if (wNumColors) { // Заказываем память для палитры hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * wNumColors);

if (!hLogPal) { GlobalUnlock(hDib); return NULL; }

// Получаем указатель на палитру lpPal = (LPLOGPALETTE)GlobalLock(hLogPal);

// Заполняем заголовок lpPal->palVersion = 0x300; lpPal->palNumEntries = wNumColors;

// Заполняем палитру for (i = 0; i < wNumColors; i++) { lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;

lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;

lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;

lpPal->palPalEntry[i].peFlags = 0; }

// Создаем палитру hPal = CreatePalette(lpPal); if (!hPal) { GlobalUnlock(hLogPal); GlobalFree(hLogPal); return NULL; }

GlobalUnlock(hLogPal); GlobalFree(hLogPal); }

GlobalUnlock(hDib);

// Возвращаем идентификатор созданной палитры return hPal; }

Опишем функции, определенные в файле dib.cpp.


Содержание раздела