Графический интерфейс GDI в Microsoft Windows (2)

         

Информация о bmpфайле



Рис 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.



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