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)\0*.bmp\0") TEXT("All Files(*.*)\0*.*\0\0"); 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\0" END 2 TEXTINCLUDE BEGIN "#include ""winres.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Menu // DIBCONV MENU BEGIN POPUP "&File" BEGIN MENUITEM "&Open...\tCtrl+O", IDM_FILE_OPEN END END ///////////////////////////////////////////////////////////////////////////// // // Accelerator // DIBCONV ACCELERATORS BEGIN "^O", IDM_FILE_OPEN, ASCII, NOINVERT END #endif // 中文(简体,中国) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED
15.3.2 从DDB到DIB
(1)GetDIBits函数——将DDB转成DIB(即从hBitmap中获得pInfo,pBits等信息)
参数 |
说明 |
hdc |
设备环境句柄 |
hBitmap |
要获取像素位的位图句柄 |
yScan |
要转换的第一行扫描线 |
cyScans |
扫描线的行数 |
pBits |
将hBitmap的像素位读入该内存中。 |
pInfo |
指向DIB信息头的指针 |
fClrUse |
颜色使用标志 |
注意:
①这个函数并不是SetDIBits的简单逆运算而己。因为DIB转为设备相关的格式时,会有信息的丢失。
②实际上很少用到这个函数,因为如果有能拿hBitmap句柄,却没有位图数据信息的情况很少(如剪贴板),但剪贴板提供了自动转换为DIB的功能。
15.3.3 DIB 区块(DIB Section)
(1)DDB和DIB的区别
区别 |
DDB(Windows内部结构) |
DIB(数据结构是己公布的) |
颜色组织 |
必须是黑白或与实际输出设备一样的格式(不含颜色表,,像素值表示索引或黑白,因数据结构未公布,不能直接访问像素位) |
采用几种颜色格式之一(可以有自己的颜色表,像素位可直接访问) |
每行像素数 |
2的倍数 |
4的倍数 |
对象构成 |
一个GDI位图对象,要通过选入内存dc来更改像素位或绘图.用一个hBitmap位图句柄来表示。 使用方法: //加载或创建DDB,而资源位图本身是DIB hBitmap =LoadBitmap(…) //创建兼容DC,因为是设备相关的。 hdcMem = CreateCompatibleDC(hdc); //选入dc SelectObject(hdc,hBitmap); //画图,改变hBitmap像素位 Rectange(hdcMem…) //显示到设备环境中 BitBlt(hdc,…,hdcMem…,SRCCOPY); //删除等 DeleteDC(hdcMem); |
是个文件或内存区域,内存结构与文件结构类似,可直接通过pBits更改像素位。 使用方法: //读入位图文件 hFile = CreateFile(…); //从文件中DIB位图读入整个或部分DIB的信息 //分配文件头内存,读入信息 pbmhf =malloc(…);//文件头 pbmi = malloc(…);//信息头 pBits = malloc(…); //像素位数据 //读入各部分的信息 ReadFile(hFile,&pbmhf,….) … //显示 SetDIBtoDevice(hdc,…);//输出,可以不需要内存兼容DC(因为设备无关) |
存在形式 |
只能存在于内存中 |
可存在于内存或文件中 |
转换 |
可相互转换,但涉及设备无关的像素位与设备相关像素位的转换 |
(2)CreateDIBSection函数——返回的对象是个“杂种”:即是GDI位图对象(DDB),又更像DIB(有pBits和pInfo),意味着可以选入设备环境修改像素位,也可以直接修改像素位。
参数 |
说明 |
hdc |
设备环境句柄,只有在fClrUse设为DIB_PAL_COLORS时才可以要设置hdc。当fClrUse设为DIB_RGB_COLORS时,hdc将被忽略。 |
pInfo |
指向DIB信息的指针 |
fClrUse |
颜色使用标志——DIB_RGB_COLORS或DIB_PAL_COLORS。 |
ppBits |
指向像素位指针的指针。 1、该函数调用时,会把pBits设置成指向某个内存块的指针(该内存由系统管理,DeleteObject(hBitmap)时自动释放,调用函数时,实际上并未为该空间预留大小,只有在赋值时,才会占用空间,我们的程序也不需要自己为pBits分配空间),在调用该函数完后,程序可以从DIB文件中读入像素位到pBits指向的这块内存里。 2、可以将位图选入内存设备中,然后用GDI在上面绘图,其结果反映在由pBits指向的DIB像素位中,但因GDI采用批量处理,所以绘图结束后,要调用GDIFlush,以便真正的保存起来,也可以“手工”地访问像素位。 |
hSection |
文件映射对象句柄 |
dwOffSet |
像素位数据在上述对象中的偏移。MSDN指出,这个参数必须是4的倍数。 |
注意:创建出来的位图对象,是每行的字节数是4的倍数,也就是更像DIB。 |
(3)应用举例
/*创建384*256像素的DIB,每个像素为24位*/ BITMAPINFOHEADER bmih; BYTE* pBits; HBITMAP hBitmap; bmih.biSize = sizeof(BITMAPINFOHEADER); bmih.biWidth = 384; bmih.biHeight = 256; bmih.biPlanes = 1; bmih.biBitCount = 24; bmih.biCompression = BI_RGB; bmih.biSizeImage = 0; bmih.biXPelsPerMeter = 0; bmih.biYPelsPerMeter = 0; bmih.biClrUsed = 0; bmih.biClrImportant = 0; /* 1、因24位,没颜色表,所以可以直接将bmih指针转为BITMAPINFO指针。 2、初始时pBits等于NULL,该函数会把pBits指针掰过来指向由系统维护的某内存块,我们的程序不必为pBits分配空间大小,在赋值是操作系统会自行分配,删除位图对象后该空间也会自行释放,程序不必自己释放。 */ hBitmap = CreateDIBSection(NULL, (BITMAPINFO*)&bmih, 0, &pBits, NULL, 0); //从DIB文件中读入像素位到pBits中。 ReadFile(hFile, &pBits, ...);
(4)获取DIB区块信息——GetObject(hBitmap,sizeof(DIBSECTION),&dibsection);
DIBSECTION字段 |
含义 |
BITMAP dsBm |
BITMAP结构 |
BITMAPINFOHEADER dsBmih |
DIB信息头 |
DWORD dsBitfields[3] |
颜色遮罩 |
HANDLE dshSection |
文件映射对象句柄 |
DWORD dsOffset |
像素位数据的位移 |
注意: 1、该函数只能用在CreateDIBSection创建的位图对象,不能用在其他创建位图的函数返回的句柄上。 2、CreateDIBSection也可以通过GetObject(hBitmap,sizeof(BITMAP),&bm)返回位图信息。 3、该结构体不包括颜色表,如果用获得颜色表,可以将位图选入内存DC后,调用GetDIBColorTable来获得。 |
(5)DIB显示到屏幕——必须从设备无关的像素转换到设备相关的像素
函数 |
格式转换时机 |
SetDIBitsToDevice StretchDIBits |
发生在函数中 |
CreateDIBitmap SetDIBits |
1、未设置CBM_INIT时,发生在用 BitBlt或StretchBlt显示的时候或SetDIBits时 2、设置CBM_INIT时:发生在CreateDIBitmap函数中 |
CreateDIBSection创建区块 |
发生在用BitBlt或StretchBlt显示函数中。(注意:CreateDIBSection返回句柄实际上是DIB,但可以用BitBlt和StretchBlt函数显示),再次说明该返回值是个杂种,兼有DDB和DIB的特点。 |
(6)文件映射选项——CreateDIBSection的最后两个参数
①文件映射:把文件当作是己经存在于内存中,可以通过内存指针来访问,但并不需要把文件完全放到内存中。
②这项技术可减少内存需要。DIB像素位可保存在磁盘上,但却可以像内存一样的访问。但像素位必须保存在另外的文件中,不能是实际DIB文件的一部分。
hFile = CreateFile(szFileName,…);
…… //读入文件头(BITMAPFILEINFO)和信息头(BITMAPINFOHEADER)
hFileMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,0,NULL);
hBitmap = CreateDIBSection(NULL,pbmi,DIB_RGB_COLORS,&pBits,
hFileMap,bmfh.bfOffBits);//bfOffBits永远不会是4的倍数!
//与MSDN要求不符,该代码不能用。
【DIBSecion程序】
效果图
/*------------------------------------------------------------ DIBSECTION.C --Displays a DIB Section in the Client area (c) Charles Petzold, 1998 ------------------------------------------------------------*/ #include <windows.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); static TCHAR szAppName[] = TEXT("DibSection"); 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 Section Display"), // 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 CreateDibSectionFromDibFile(PTSTR szFileName) { HBITMAP hBitmap; BITMAPFILEHEADER bmfh; BITMAPINFO* pbmi; BYTE* pBits; BOOL bSuccess; HANDLE hFile; DWORD dwInfoSize, dwBytesRead; //打开位图,可读可写 hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hFile == INVALID_HANDLE_VALUE) return NULL; //与前一个程序(DIBConv)不同,这里不读入整个文件,而是只读取文件头 bSuccess = ReadFile(hFile, &bmfh, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL); if (!bSuccess || (dwBytesRead != sizeof(BITMAPFILEHEADER)) || (bmfh.bfType != *(WORD*)"BM")) { CloseHandle(hFile); return NULL; } //为BITMAPINFO分配内存,并读入数据 dwInfoSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER); pbmi = malloc(dwInfoSize); bSuccess = ReadFile(hFile, pbmi, dwInfoSize, &dwBytesRead, NULL); //创建DDB——函数调用后,pBits指针会被掰向,一个存放像素数的内存,该内存由系统维护。 hBitmap = CreateDIBSection(NULL, pbmi, DIB_RGB_COLORS, &pBits, NULL, 0); //为像素位内存写入像素数据 ReadFile(hFile, pBits, bmfh.bfSize - bmfh.bfOffBits, &dwBytesRead, NULL); free(pbmi); CloseHandle(hFile); return hBitmap; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static TCHAR szFilter[] = TEXT("Bitmap File(*.bmp)\0*.bmp\0") TEXT("All Files(*.*)\0*.*\0\0"); 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(或DIB区块) hdc = GetDC(hwnd); hBitmap = CreateDibSectionFromDibFile(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++ 生成的包含文件。 // 供 DIBSection.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
//DibSection.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\0" END 2 TEXTINCLUDE BEGIN "#include ""winres.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Menu // DIBSECTION MENU BEGIN POPUP "&File" BEGIN MENUITEM "&Open...\tCtrl+O", IDM_FILE_OPEN END END ///////////////////////////////////////////////////////////////////////////// // // Accelerator // DIBSECTION ACCELERATORS BEGIN "^O", IDM_FILE_OPEN, ASCII, NOINVERT END #endif // 中文(简体,中国) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED