Фрагмент файла bmpinfo/dib.cpp
// ----------------------------------------------------- // Функции для работы с файлами в формате DIB // ----------------------------------------------------- #define STRICT #include <windows.h>
#include <windowsx.h>
#include <commdlg.h>
#include <mem.h>
#pragma hdrstop #include "dib.hpp"
// ------------------------------- // Функция SizeToHiMetric // Преобразование ширины и высоты для // режима отображения MM_HIMETRIC // ------------------------------- static void SizeToHiMetric(int *width, int *height) { HDC hDC = GetDC(0);
if(hDC) { // Определяем количество пикселов на один // логический дюйм по горизонтали и вертикали int dpiX = GetDeviceCaps(hDC, LOGPIXELSX);
int dpiY = GetDeviceCaps(hDC, LOGPIXELSY);
// Константа для пересчета const long HiMetricPerInch = 2540;
// Выполняем пересчет if(width) *width = int (*width * HiMetricPerInch / dpiX);
if(height) *height = int (*height * HiMetricPerInch / dpiY);
ReleaseDC(0, hDC);
} }
// ------------------------------- // Функция DIBCopyToClipboard // Копирование DIB в Clipboard // ------------------------------- BOOL DIBCopyToClipboard(HDIB hDib, HWND hwnd) { POINT ptSize; HDC hdcMeta, hdc, hdcMem; HMETAFILE hMF; HBITMAP hBitmap; HPALETTE hPal, hOldPal; HGLOBAL hMeta; LPMETAFILEPICT lpMeta; int x, y;
// Если DIB не загружен или он имеет тип, // отличный от WINRGB_DIB, копирование не выполняем if(hDib == NULL) return FALSE; if(DIBType(hDib) != WINRGB_DIB) return FALSE;
// Открываем и очищаем Clipboard if(!OpenClipboard(hwnd)) return FALSE; EmptyClipboard();
// Определяем размеры DIB DIBGetBmpRect(hDib, &ptSize);
x = ptSize.x; y = ptSize.y;
// Создаем DDB // Копируем в него содержимое окна, // размеры копируемой области равны // размерам DIB hdc = GetDC(hwnd);
hdcMem = CreateCompatibleDC(hdc);
hBitmap = CreateCompatibleBitmap(hdc, x, y);
if(hBitmap) { SelectObject(hdcMem, hBitmap);
StretchBlt(hdcMem, 0, 0, x, y, hdc, 0, 0, x, y, SRCCOPY);
} DeleteDC(hdcMem);
ReleaseDC(hwnd, hdc);
// Создаем метафайл в памяти hdcMeta = CreateMetaFile((LPSTR)NULL);
// Устанавливаем начало координат и размеры изображения SetWindowOrgEx(hdcMeta, 0, 0, NULL);
SetWindowExtEx(hdcMeta, ptSize.x, ptSize.y, NULL);
// Создаем палитру из DIB hPal = DIBCreatePalette(hDib);
if(hPal) { // Выбираем и реализуем палитру в контекст // метафайла hOldPal = SelectPalette(hdcMeta, hPal, FALSE);
RealizePalette(hdcMeta);
}
// Рисуем DIB в контексте метафайла DIBPaint(hdcMeta, 0, 0, hDib);
// Выбираем старую палитру if(hPal) SelectPalette(hdcMeta, hOldPal, FALSE);
// Закрываем метафайл hMF = CloseMetaFile(hdcMeta);
// Заказываем память для заголовка метафайла hMeta = GlobalAlloc(GHND, sizeof(METAFILEPICT));
lpMeta = (LPMETAFILEPICT)GlobalLock(hMeta);
// Преобразуем координаты для // режима отображения MM_HIMETRIC SizeToHiMetric(&x, &y);
// Заполняем заголовок метафайла lpMeta->
mm = MM_ANISOTROPIC; lpMeta->
xExt = x; lpMeta->
yExt = y; lpMeta->
hMF = hMF;
// Расфиксируем память заголовка метафайла GlobalUnlock(hMeta);
// Записываем метафайл в Clipboard if(hMeta) SetClipboardData(CF_METAFILEPICT, hMeta);
// Записываем DDB в Clipboard if(hBitmap) SetClipboardData(CF_BITMAP, hBitmap);
// Записываем палитру в Clipboard if(hPal) SetClipboardData(CF_PALETTE, hPal);
// Закрываем Clipboard CloseClipboard();
return TRUE; }
Функция SizeToHiMetric предназначена для преобразования значений ширины и высоты изображения из пикселов в сотые доли миллиметра. Напомним, что при заполнении заголовка метафайла в изотропном и анизотропном режиме отображения размеры изображения указываются в сотых долях миллиметра.
Для выполнения преобразования функция SizeToHiMetric определяет количество пикселов в одном логическом дюйме для контекста отображения, связанного с экраном дисплея. Далее ширина (высота) изображения (в пикселах) умножается на значение 2540 (1 дюйм соответствует 25,4 миллиметра) и делится на количество пикселов в одном логическом дюйме.
Функция DIBCopyToClipboard выполняет копирование данных в Clipboard одновременно в нескольких форматах, используя методики, описанные нами в предыдущих разделах.Для определения размеров DIB вызывается функция DIBGetBmpRect, определенная в файле dib.cpp (в листинге не представлена).