第15章 设备无关位图_15.3 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, , , NULL);//单色位图 //后面4个参数是用来初始化DDB的
if (fInit == CBM_INIT)
{
hdcMem = CreateCompatibleDC(hdc);
SelectObject(hdcMem, hBitmap); //在内存位图表面绘图,注意这里是DDB位图,己被选入内存DC
SetDIBitsToDevice(hdcMem, , , cx, cy, , , , 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 = ;
wndclass.cbWndExtra = ;
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 ;
} 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, , ))
{
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 + ),
CBM_INIT,
(BYTE*)pbmfh + pbmfh->bfOffBits,
(BITMAPINFO*)(pbmfh + ),
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, , 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 ;
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return ;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_FILE_OPEN:
//显示打开对话框
if (!GetOpenFileName(&ofn))
return ;
//删除己经打开的位图
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 ;
}
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps); if (hBitmap)
{
GetObject(hBitmap, sizeof(BITMAP), &bitmap);
hdcMem = CreateCompatibleDC(hdc);
SelectObject(hdcMem, hBitmap);
BitBlt(hdc, , , bitmap.bmWidth, bitmap.bmHeight, hdcMem, , , SRCCOPY);
DeleteDC(hdcMem);
}
EndPaint(hwnd, &ps);
return ; case WM_DESTROY:
if (hBitmap)
DeleteObject(hBitmap);
PostQuitMessage();
return ;
}
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
//
TEXTINCLUDE
BEGIN
"resource.h\0"
END
TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
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 = ;
bmih.biHeight = ;
bmih.biPlanes = ;
bmih.biBitCount = ;
bmih.biCompression = BI_RGB;
bmih.biSizeImage = ;
bmih.biXPelsPerMeter = ;
bmih.biYPelsPerMeter = ;
bmih.biClrUsed = ;
bmih.biClrImportant = ;
/*
1、因24位,没颜色表,所以可以直接将bmih指针转为BITMAPINFO指针。
2、初始时pBits等于NULL,该函数会把pBits指针掰过来指向由系统维护的某内存块,我们的程序不必为pBits分配空间大小,在赋值是操作系统会自行分配,删除位图对象后该空间也会自行释放,程序不必自己释放。
*/
hBitmap = CreateDIBSection(NULL, (BITMAPINFO*)&bmih, , &pBits, NULL, );
//从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 = ;
wndclass.cbWndExtra = ;
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 ;
} 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, , ))
{
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, );
//为像素位内存写入像素数据
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, , 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 ;
case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return ;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_FILE_OPEN:
//显示打开对话框
if (!GetOpenFileName(&ofn))
return ;
//删除己经打开的位图
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 ;
}
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps); if (hBitmap)
{
GetObject(hBitmap, sizeof(BITMAP), &bitmap);
hdcMem = CreateCompatibleDC(hdc);
SelectObject(hdcMem, hBitmap);
BitBlt(hdc, , , bitmap.bmWidth, bitmap.bmHeight, hdcMem, , , SRCCOPY);
DeleteDC(hdcMem);
} EndPaint(hwnd, &ps);
return ; case WM_DESTROY:
if (hBitmap)
DeleteObject(hBitmap);
PostQuitMessage();
return ;
}
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
//
TEXTINCLUDE
BEGIN
"resource.h\0"
END
TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
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
第15章 设备无关位图_15.3 DIB和DDB的结合的更多相关文章
- 第15章 设备无关位图_15.1 DIB文件格式
15.1 DIB文件格式(一种文件格式,扩展名为BMP) 15.1.1 OS/2风格的DIB 文件格式 字段 说明 文件头 (BITMAPFILEHEADER) 1.共14个字节 2.缩写建议用bmf ...
- 第15章 设备无关位图_15.2 显示和打印DIB
15.2.1 探究DIB (1)DIB文件的结构 整个文件 紧凑DIB(整个文件除文件头) 文件头(File Header) 信息头(Information Header) 信息头(Informati ...
- device-independent bitmap (DIB) 设备无关位图
设备无关位图即独立于设备的位图(DIB)与"Device-Dependent Bitmaps (DDB) 设备相关位图"相比,它不再依赖于具体的设备,从而更适合在不同的计算机之间传 ...
- windows设备相关位图与设备无关位图
windows支持两种位图格式,DDB(device-dependent bitmap),DIB(device-independent bitmap).设备相关位图用于windows显示系统中,其图像 ...
- Device-Dependent Bitmaps (DDB) 设备相关位图
设备相关的位图(DDB)使用单一结构BITMAP结构描述.该结构的成员指定矩形区域的宽度和高度,以像素为单位;将条目从设备调色板映射到像素的数组的宽度;以及器件的颜色格式,在每个像素的颜色平面和位数方 ...
- ASM:《X86汇编语言-从实模式到保护模式》第15章:任务切换
15章其实应该是和14章相辅相成的(感觉应该是作者觉得14章内容太多了然后切出来了一点).任务切换和14章的某些概念是分不开的. ★PART1:任务门与任务切换的方法 1. 任务管理程序 14章的时候 ...
- Linux就这个范儿 第15章 七种武器 linux 同步IO: sync、fsync与fdatasync Linux中的内存大页面huge page/large page David Cutler Linux读写内存数据的三种方式
Linux就这个范儿 第15章 七种武器 linux 同步IO: sync.fsync与fdatasync Linux中的内存大页面huge page/large page David Cut ...
- unix network programming(3rd)Vol.1 [第13~15章]《读书笔记系列》
第13章 守护进程和inetd 超级服务器 syslog() daemon_init() setuid() setgid() 第14章 高级IO 标准I/O函数库,支持3种缓冲 缓冲(读写存储设备(硬 ...
- 【RL-TCPnet网络教程】第15章 RL-TCPnet之创建多个TCP连接
第15章 RL-TCPnet之创建多个TCP连接 本章节为大家讲解RL-TCPnet的TCP多客户端实现,因为多客户端在实际项目中用到的地方还挺多,所以我们也专门开启一个章节做讲解.另外,学习 ...
随机推荐
- angularjs 指令—— 绑定策略(@、=、&)
angularjs 指令—— 绑定策略(@.=.&) 引入主题背景:angular 的指令配置中的template可以直接使用硬编码写相应的代码,不过也可以根据变量,进行动态更新.那么需要用到 ...
- JavaScript 经典实例收集整理
跨浏览器添加事件 //跨浏览器添加事件 function addEvent(obj,type,fn){ if(obj.addEventListener){ obj.addEventListener(t ...
- HTML5移动开发学习笔记
最近做webapp项目过程中,发现坑还是挺多的,以下是网络收集一些开发中的常见问题及知识汇总,以便查阅,慢慢更新:). meta 基础知识 H5页面窗口自动调整到设备宽度,并禁止用户缩放页面 < ...
- Office 365 - SharePoint 2013 Online之添加App开发工具Napa
1.新建一个网站集,模板选择开发人员模板,如下图: 2.确定以后,需要稍等一会儿; 3.点击网站内容,添加app,如下图: 4.进入SharePoint Store,选择Napa,如下图: 5.选择A ...
- Android Studio常用快捷键
Ctrl+U :如果你的光标在重写父类的一个方法内(如:Activity#onCreate()),这个将会跳到父类的实现上. 如果你的光标在类名上,它将会跳到父类. Ctrl+Alt+Home:它可以 ...
- Udp通讯(零基础)
前面学习了Tcp通讯之后听老师同学们讲到Udp也可以通讯,实现还要跟简单,没有繁琐的连接,所以最近学习了一下,记录下来以便忘记,同时也发表出来与大家相互学习,下面是我自己写的一个聊天例子,实现了群聊私 ...
- 修改mac host
/etc/hosts 把host 复制到桌面 修改 然后 替换原来的
- 窗口activity
android:theme="@style/FloatActivity" E:\day9\mobilesafe\res\values\style
- 安装docker后,VMware网络无法访问了,VMware重置网络设置
1.vmware虚拟机处于关闭状态 2.vmware程序->edit(编辑)-->左下角 "Restore Default"恢复默认设置 [恢复]完成后 ...
- jQuery代码优化:事件委托篇
推荐阅读原文:http://www.ituring.com.cn/article/467# 推荐11收藏 随着DOM结构的复杂化和Ajax等动态脚本技术的运用,事件委托自然浮出了水面.jQuery为绑 ...