第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, , , 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的结合的更多相关文章

  1. 第15章 设备无关位图_15.1 DIB文件格式

    15.1 DIB文件格式(一种文件格式,扩展名为BMP) 15.1.1 OS/2风格的DIB 文件格式 字段 说明 文件头 (BITMAPFILEHEADER) 1.共14个字节 2.缩写建议用bmf ...

  2. 第15章 设备无关位图_15.2 显示和打印DIB

    15.2.1 探究DIB (1)DIB文件的结构 整个文件 紧凑DIB(整个文件除文件头) 文件头(File Header) 信息头(Information Header) 信息头(Informati ...

  3. device-independent bitmap (DIB) 设备无关位图

    设备无关位图即独立于设备的位图(DIB)与"Device-Dependent Bitmaps (DDB) 设备相关位图"相比,它不再依赖于具体的设备,从而更适合在不同的计算机之间传 ...

  4. windows设备相关位图与设备无关位图

    windows支持两种位图格式,DDB(device-dependent bitmap),DIB(device-independent bitmap).设备相关位图用于windows显示系统中,其图像 ...

  5. Device-Dependent Bitmaps (DDB) 设备相关位图

    设备相关的位图(DDB)使用单一结构BITMAP结构描述.该结构的成员指定矩形区域的宽度和高度,以像素为单位;将条目从设备调色板映射到像素的数组的宽度;以及器件的颜色格式,在每个像素的颜色平面和位数方 ...

  6. ASM:《X86汇编语言-从实模式到保护模式》第15章:任务切换

    15章其实应该是和14章相辅相成的(感觉应该是作者觉得14章内容太多了然后切出来了一点).任务切换和14章的某些概念是分不开的. ★PART1:任务门与任务切换的方法 1. 任务管理程序 14章的时候 ...

  7. 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 ...

  8. unix network programming(3rd)Vol.1 [第13~15章]《读书笔记系列》

    第13章 守护进程和inetd 超级服务器 syslog() daemon_init() setuid() setgid() 第14章 高级IO 标准I/O函数库,支持3种缓冲 缓冲(读写存储设备(硬 ...

  9. 【RL-TCPnet网络教程】第15章 RL-TCPnet之创建多个TCP连接

    第15章     RL-TCPnet之创建多个TCP连接 本章节为大家讲解RL-TCPnet的TCP多客户端实现,因为多客户端在实际项目中用到的地方还挺多,所以我们也专门开启一个章节做讲解.另外,学习 ...

随机推荐

  1. mvc model 传值两种方式区别

    1: controller中: public actionresult index() { M m=new M(); return view(m) } view中: @model.phone vs 中 ...

  2. css中的background属性

    第一次写博客,我就写写今天在编写网页的过程中,对background的两种运用,一是background中的线性渐变,对背景的渐变我其实是很少使用的,所以今天在写的时候我用css3的帮助手册,back ...

  3. SharePoint 解决打开浏览器自动登录

    SharePoint使用Windows身份验证,默认会弹出Windows验证登录框,如下图所示: 1.对于已经加域的客户端 IE安全设置,将站点加信任站点,然后修改信任站点安全设置, 滚动条拉到最后, ...

  4. Servlet基础(一) Servlet简介 关键API介绍及结合源码讲解

    Servlet基础(一) Servlet基础和关键的API介绍 Servlet简介 Java Servlet是和平台无关的服务器端组件,它运行在Servlet容器中. Servlet容器负责Servl ...

  5. AVAudioSession初探

    根据文档,AudioSession规定了app和系统音频行为交互的规范,一个app只有一个AudioSession的单例. app通过设置自己AudioSession的单例的属性来告诉系统自身想达到的 ...

  6. 01_iOS开发需要准备什么?

    本文目录 一. 前言 二.IOS开发准备 前言 相信现在的你已经有了一台安装了Xcode或者搭建好Objective-C的电脑了,由于我自己装了黑苹果,所以以后的内容都会直接从黑苹果上运行的Xcode ...

  7. Provisioning Profile文件在哪找?

    ~/Library/MobileDevice/Provisioning Profiles

  8. 【代码笔记】iOS-等待动画

    一,效果图. 二,工程图. 三,代码. RootViewController.h #import <UIKit/UIKit.h> @interface RootViewController ...

  9. Swift 初步了解

    Swift 初步了解 前言: 本篇博客会结合OC对Swift进行简单介绍. OC 用NSLog输出日志 NSLog(@"旭宝爱吃鱼"); Swift 用print输出日志 prin ...

  10. C#语言基础——特殊集合

    特殊集合一.stack集合栈:stack,先进后出,一个一个赋值,一个一个取值,按顺序,且没有索引属性和方法:.count 取集合内元素的个数.push() 将元素一个一个推入集合中.pop() 将元 ...