第15章 设备相关位图_15.3 DIB和DDB的结合
15.3.1 从DIB创建DDB
(1)hBitmap =CreateDIBitmap(…)——注意这名称会误导,实际上创建的是DDB
参数 |
说明 |
hdc |
设备环境句柄,可以为NULL。 |
pInfoHdr |
指向DIB信息头的指针,即BITMAPINFOHEADER |
fInit |
0或CBM_INIT。CBM_INIT指定用后面3个参数来初始化DDB中的像素位 |
pBits |
DIB像素位的指针 |
pInfo |
DIB信息指针,即BITMAPINFO(包含BITMAPINFOHEADER和颜色表) |
fClrUse |
颜色使用标志位:DIB_RGB_COLORS(0)或DIB_PAL_COLORS(1) |
注意:①返回值:跟CreateBitmap一样都返回一个GDI位图对象,可以直接选入DC中,并在上面绘图,以改变像素位。
②名称会误导,它是从一个DIB中创建一个DDB。
(2)CreateDIBitmap函数内部大致的代码实现
HBITMAP CreateDIBitmap(HDC hdc, CONST BITMAPINFOHEADER* pbmih, DWORD fInit, CONST VOID* pBits,CONST BITMAPINFO* pbmi, UINT fUsage) { HBITMAP hBitmap; HDC hdc,hdcMem; int cx, cy, iBitCount; //从第2个参数读取DIB信息头的信息 if (pbmih->biSize == sizeof(BITMAPCOREHEADER)) { cx = ((PBITMAPCOREHEADER)pbmih)->bcWidth; cy = ((PBITMAPCOREHEADER)pbmih)->bcHeight; iBitCount = ((PBITMAPCOREHEADER)pbmih)->bcBitCount; } else { cx = pbmih->biWidth; cy = pbmih->biHeight; iBitCount = pbmih->biBitCount; } //创建DDB if (hdc) hBitmap = CreateCompatibleBitmap(hdc, cx, cy); else hBitmap = CreateBitmap(cx, cy, 1, 1, NULL);//单色位图 //后面4个参数是用来初始化DDB的 if (fInit == CBM_INIT) { hdcMem = CreateCompatibleDC(hdc); SelectObject(hdcMem, hBitmap); //在内存位图表面绘图,注意这里是DDB位图,己被选入内存DC SetDIBitsToDevice(hdcMem, 0, 0, cx, cy, 0, 0, 0, cy, pBits, pbmi, fUsage); DeleteDC(hdcMem); } return hBitmap; }
(3)应用举例
①创建单色GDI位图:hBitmap =CreateDIBitmap(NULL,pbmih,0,NULL,NULL,0);
②DC兼容位图:hBitmap = CreateDIBitmap(hdc,pbmih,0,NULL,NULL,0);//未初始化
(4)当CreateDIBitmap时未初始化像素位,后期可调用SetDIBits初始化DDB像素位
参数 |
说明 |
hdc |
设备环境句柄,当DIB_PAL_COLORS时才需要设备hdc |
hBitmap |
要设置像素位的位图句柄 |
yScan |
要转换的第一行扫描线 |
cyScans |
扫描线的行数 |
pBits |
将该像素位设给hBitmap的像素位。 |
pInfo |
指向DIB信息头的指针 |
fClrUse |
颜色使用标志 |
【DIBCONV程序】
/*------------------------------------------------------------ DIBCONV.C --Converts a DIB to a DDB (c) Charles Petzold, 1998 ------------------------------------------------------------*/ #include <windows.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); static TCHAR szAppName[] = TEXT("DibConv"); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HWND hwnd; MSG msg; WNDCLASSEX wndclass; HACCEL hAccel; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.cbSize = sizeof(WNDCLASSEX); wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(hInstance, szAppName); wndclass.hIconSm = LoadIcon(hInstance, szAppName); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = szAppName; wndclass.lpszClassName = szAppName; if (!RegisterClassEx(&wndclass)) { MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppName, // window class name TEXT("DIB to DDB Conversion"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL); // creation parameters ShowWindow(hwnd, iCmdShow); UpdateWindow(hwnd); hAccel = LoadAccelerators(hInstance, szAppName); while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(hwnd, hAccel, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } HBITMAP CreateBitmapObjectFromDibFile(HDC hdc, PTSTR szFileName) { HBITMAP hBitmap; BITMAPFILEHEADER* pbmfh; BOOL bSuccess; HANDLE hFile; DWORD dwFileSize, dwHighSize, dwBytesRead; //打开位图,可读可写 hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hFile == INVALID_HANDLE_VALUE) return NULL; //读入整个文件 dwFileSize = GetFileSize(hFile, &dwHighSize); if (dwHighSize) { CloseHandle(hFile); return NULL; } pbmfh = malloc(dwFileSize); if (!pbmfh) { CloseHandle(hFile); return NULL; } bSuccess = ReadFile(hFile, pbmfh, dwFileSize, &dwBytesRead, NULL); CloseHandle(hFile); //检验是否是位图 if (!bSuccess || (dwBytesRead != dwFileSize) || (pbmfh->bfType != *(WORD*)"BM")) { free(pbmfh); return NULL; } //创建DDB——注意,这里读入整个文件,并从该DIB文件读入信息头、像素位等信息 hBitmap = CreateDIBitmap(hdc, (BITMAPINFOHEADER*)(pbmfh + 1), CBM_INIT, (BYTE*)pbmfh + pbmfh->bfOffBits, (BITMAPINFO*)(pbmfh + 1), DIB_RGB_COLORS); free(pbmfh); return hBitmap; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static TCHAR szFilter[] = TEXT("Bitmap File(*.bmp) *.bmp ") TEXT("All Files(*.*) *.* "); static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH]; static cxClient, cyClient; static HBITMAP hBitmap; HDC hdc, hdcMem; PAINTSTRUCT ps; BITMAP bitmap; static OPENFILENAME ofn; switch (message) { case WM_CREATE: memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hwnd; ofn.lpstrFilter = szFilter; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrTitle = szTitleName; ofn.nMaxFileTitle = MAX_PATH; ofn.lpstrDefExt = TEXT("*.bmp"); return 0; case WM_SIZE: cxClient = LOWORD(lParam); cyClient = HIWORD(lParam); return 0; case WM_COMMAND: switch (LOWORD(wParam)) { case IDM_FILE_OPEN: //显示打开对话框 if (!GetOpenFileName(&ofn)) return 0; //删除己经打开的位图 if (hBitmap) { DeleteObject(hBitmap); hBitmap = NULL; } SetCursor(LoadCursor(NULL, IDC_WAIT)); ShowCursor(TRUE); //从DIB位图文件中创建DDB hdc = GetDC(hwnd); hBitmap = CreateBitmapObjectFromDibFile(hdc, szFileName); ReleaseDC(hwnd, hdc); ShowCursor(FALSE); SetCursor(LoadCursor(NULL, IDC_ARROW)); //更新客户区内容 InvalidateRect(hwnd, NULL, TRUE); //错误提示 if (hBitmap == NULL) { MessageBox(hwnd, TEXT("Cannot load DIB file"), szAppName, MB_OK | MB_ICONEXCLAMATION); } return 0; } break; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); if (hBitmap) { GetObject(hBitmap, sizeof(BITMAP), &bitmap); hdcMem = CreateCompatibleDC(hdc); SelectObject(hdcMem, hBitmap); BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY); DeleteDC(hdcMem); } EndPaint(hwnd, &ps); return 0; case WM_DESTROY: if (hBitmap) DeleteObject(hBitmap); PostQuitMessage(0); return 0; } return DefWindowProc(hwnd, message, wParam, lParam); }
//resource.h
//{{NO_DEPENDENCIES}} // Microsoft Visual C++ 生成的包含文件。 // 供 DIBConv.rc 使用 // #define IDM_FILE_OPEN 40001 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 103 #define _APS_NEXT_COMMAND_VALUE 40004 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif
//DibConv.rc
// Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "winres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // 中文(简体,中国) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS) LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h " END 2 TEXTINCLUDE BEGIN "#include ""winres.h"" " "