15.2.1 探究DIB

(1)DIB文件的结构

整个文件

紧凑DIB(整个文件除文件头)

文件头(File Header)

信息头(Information Header)

信息头(Information Header)

颜色表(Color Table)

颜色表(Color Table)

像素位(Pixel Bits)

像素位(Pixel Bits)

注意:①紧凑DIB在内存中是连续的,即整个DIB存在单个内存块中

②DIB载入内存时,像素位与信息头可以分别存在两个内存块,即内存不连续。

(2)像素位指针的求法

15.2.2 从像素到像素

(1)SetDIBitsToDevice函数——显示没有拉伸和压缩的DIB

参数

含义

hdc

设备环境句柄

xDst

目标矩形左上角x坐标(逻辑单位),这里的“左上角”指视觉上图像的左上角。

yDst

目标矩形左上角y坐标(逻辑单位)

cxSrc

源矩形宽度

1、这四个参数可以决定是显示整个DIB或只显示一部分。

2、对于自上而下的DIB,因BITMAPINFOHEADER的biHeight为负数,所以cySrc应设置为biHeight的绝对值,即biHeight永远要设为正数。

3、无论映射模式怎样,在输出设备上显示的DIB总是cxSrc像素宽,cySrc像素高。

cySrc

源矩形高度

xSrc

源x坐标

ySrc

源y坐标

yScan

指定DIB中起始扫描线的编号(见后面的详细分析)。

用来每次按顺序显示DIB的一部分。

通常yScan=0,cyScan=DIB的高度。

cyScan

DIB扫描线数目

pBits

像素位指针

pInfo

DIB信息头指针

fClrUse

指向BITMAPINFO结构中的成员bmiColors是否包含明确的RGB值或对调色板进行索引的值。取值为下列之一,这些值的含义如下:

DIB_PAL_COLORS(1):表示颜色表由16位的索引值数组组成,利用这些值可对当前选中的逻辑调色板进行索引。

DIB_RGB_COLORS(0):表示颜色表包含原义的RGB值。

返回值:返回函数调用后,显示DIB的所用的扫描行个数。

【ShowDib1程序】
效果图

/*------------------------------------------------------------
SHOWDIB1.C -- Show a DIB in the client area
(c) Charles Petzold, 1998
------------------------------------------------------------*/ #include <windows.h>
#include "resource.h"
#include "DibFile.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); static TCHAR szAppName[] = TEXT("ShowDib1");
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("Show DIB #1"), // 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;
} LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BITMAPFILEHEADER* pbmfh;
static BITMAPINFO* pbmi;
static BYTE* pBits; static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
static int cxClient, cyClient, cxDib, cyDib;
HDC hdc;
PAINTSTRUCT ps;
BOOL bSuccess; switch (message)
{
case WM_CREATE: DibFileInitialize(hwnd);
return ; case WM_INITMENUPOPUP:
EnableMenuItem((HMENU)wParam, IDM_FILE_SAVE, pbmfh ? MF_ENABLED : MF_GRAYED);
return ; case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return ; case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_FILE_OPEN:
//显示打开对话框
if (!DibFileOpenDlg(hwnd, szFileName, szTitleName))
return ; //如果DIB文件己被载入,释放内存
if (pbmfh)
{
free(pbmfh);
pbmfh = NULL;
} //将整个DIB加载到内存中
SetCursor(LoadCursor(NULL, IDC_WAIT));
ShowCursor(TRUE); pbmfh = DibLoadImage(szFileName); ShowCursor(FALSE);
SetCursor(LoadCursor(NULL, IDC_ARROW)); //使客户区无效,以便后面的绘图并擦除以前客户区显示的内容
InvalidateRect(hwnd, NULL, TRUE); if (pbmfh == NULL)
{
MessageBox(hwnd, TEXT("Cannot load DIB file"), szAppName, );
return ;
} //获取指向DIB信息头的指针和指向像素位的指针
pbmi = (BITMAPINFO*)(pbmfh + );
pBits = (BYTE*)pbmfh + pbmfh->bfOffBits; //获取图像的宽度和高度
if (pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
cxDib = ((BITMAPCOREHEADER*)pbmi)->bcWidth;
cyDib = ((BITMAPCOREHEADER*)pbmi)->bcHeight;
} else
{
cxDib = pbmi->bmiHeader.biWidth;
cyDib = abs(pbmi->bmiHeader.biHeight);
}
return ; case IDM_FILE_SAVE: //显示保存对话框
if (!DibFileSaveDlg(hwnd, szFileName, szTitleName))
return ; //将DIB位图保存到文件中
SetCursor(LoadCursor(NULL, IDC_WAIT));
ShowCursor(TRUE); bSuccess = DibSaveImage(szFileName, pbmfh); ShowCursor(FALSE);
SetCursor(LoadCursor(NULL, IDC_ARROW)); if (!bSuccess)
MessageBox(hwnd, TEXT("Cannot save DIB file"), szAppName, ); return ;
}
break; case WM_PAINT:
hdc = BeginPaint(hwnd, &ps); if (pbmfh)
{
SetDIBitsToDevice(hdc,
,
,
cxDib, //像素宽度
cyDib, //像素高度
, //xSrc
, //ySrc
, //第一扫描线
cyDib, //扫描线数目
pBits, //像素位
pbmi,
DIB_RGB_COLORS);
} EndPaint(hwnd, &ps);
return ; case WM_DESTROY:
if (pbmfh)
free(pbmfh); PostQuitMessage();
return ;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}

//DibFile.h

/*-----------------------------------------------------
DIBFILE.H ---- Header File for DIBFILE.C
------------------------------------------------------*/
#pragma once
#include <windows.h> void DibFileInitialize(HWND hwnd); BOOL DibFileOpenDlg(HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName);
BOOL DibFileSaveDlg(HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName); BITMAPFILEHEADER* DibLoadImage(PTSTR pstrFileName); BOOL DibSaveImage(PTSTR pstrFileName, BITMAPFILEHEADER*);

//DibFile.c

#include "DibFile.h"

static OPENFILENAME ofn;
void DibFileInitialize(HWND hwnd)
{
static TCHAR szFilter[] = TEXT("Bitmap Files (*.BMP)\0*.bmp\0")\
TEXT("All Files(*.*)\0*.*\0\0"); ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.hInstance = NULL;
ofn.lpstrFilter = szFilter;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = ;
ofn.nFilterIndex = ;
ofn.lpstrFile = NULL; //在打开和关闭中设置
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFileTitle = NULL; //在打开和关闭函数中设置
ofn.nMaxFileTitle = MAX_PATH;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = NULL;
ofn.Flags = ; //在打开和关闭函数中设置
ofn.nFileOffset = ;
ofn.nFileExtension = ;
ofn.lpstrDefExt = TEXT("bmp"); //默认扩展名
ofn.lCustData = ;
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
} BOOL DibFileOpenDlg(HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)
{
ofn.hwndOwner = hwnd;
ofn.lpstrFile = pstrFileName;
ofn.lpstrFileTitle = pstrTitleName;
ofn.Flags = ;
return GetOpenFileName(&ofn);
} BOOL DibFileSaveDlg(HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName)
{
ofn.hwndOwner = hwnd;
ofn.lpstrFile = pstrFileName;
ofn.lpstrFileTitle = pstrTitleName;
ofn.Flags = OFN_OVERWRITEPROMPT;
return GetSaveFileName(&ofn);
} BITMAPFILEHEADER* DibLoadImage(PTSTR pstrFileName)
{
BOOL bSuccess;
DWORD dwFileSize, dwHighSize, dwBytesRead;
HANDLE hFile;
BITMAPFILEHEADER* pbmfh; hFile = CreateFile(pstrFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hFile == INVALID_HANDLE_VALUE)
return NULL; //返回文件大小的低位字,保存在dwFileSize中,高位字保存在dwHighSize中
dwFileSize = GetFileSize(hFile, &dwHighSize); if (dwHighSize) //文件太大,超过4G则dwHighSize不为0,退出
{
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") || //位图标志“BM”
(pbmfh->bfSize != dwFileSize))
{
free(pbmfh);
return NULL;
} return pbmfh;
} BOOL DibSaveImage(PTSTR pstrFileName, BITMAPFILEHEADER* pbmfh)
{
BOOL bSuccess;
DWORD dwBytesWritten;
HANDLE hFile; hFile = CreateFile(pstrFileName, GENERIC_WRITE, , NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE)
return FALSE; bSuccess = WriteFile(hFile, pbmfh, pbmfh->bfSize, &dwBytesWritten, NULL);
CloseHandle(hFile); if ((!bSuccess) || (dwBytesWritten != pbmfh->bfSize))
{
DeleteFile(pstrFileName);
return FALSE;
}
return TRUE;
}

//resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 ShowDib1.rc 使用
//
#define IDM_FILE_OPEN 40001
#define IDM_FILE_SAVE 40002 // Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40007
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

//ShowDib1.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
// SHOWDIB1 MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Open...\tCtrl+O", IDM_FILE_OPEN
MENUITEM "&Save...\tCtrl+S", IDM_FILE_SAVE
END
END /////////////////////////////////////////////////////////////////////////////
//
// Accelerator
// SHOWDIB1 ACCELERATORS
BEGIN
"^O", IDM_FILE_OPEN, ASCII, NOINVERT
"^S", IDM_FILE_SAVE, ASCII, NOINVERT
END #endif // 中文(简体,中国) resources
///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
// /////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
 15.2.3 DIB的颠倒世界

(1)自下而上DIB坐标说明

 

源矩形

目标矩形

①(xSrc,ySrc)—内存中第一个像素!

①(xDst,yDst+cySrc-1)

②(xSrc+cxSrc-1,ySrc)

②(xDst+cxSrc-1,yDst+cySrc-1)

③(xSrc,ySrc+cySrc-1)

③(xDst,yDst)

④(xSrc+cxSrc-1,ySrc+cySrc-1)—内存最后1个像素

④(xDst+cxSrc-1,yDst)

注意:1、cxSrc,cySrc为区域宽度和高度,因为坐标从0开始,所以上面式子出现减1现象。

2、原点(0,0)位于DIB图的左下角(左图中的①),第一行的第1个像素。

(2)自上而下DIB坐标说明

 

源矩形

目标矩形

①(xSrc,ySrc+cySrc-1)—内存中第1个像素!

①(xDst,yDst)

②(xSrc+cxSrc-1,ySrc+cySrc-1)

②(xDst+cxSrc-1,yDst)

③(xSrc,ySrc)—这里不是第1 个像素!

③(xDst,yDst+cySrc-1)

④(xSrc+cxSrc-1,ySrc)—内存中最后1个像素

④(xDst+cxSrc-1,yDst+cySrc-1)

注意:1、cxSrc,cySrc为区域宽度和高度,因为坐标从0开始,所以上面式子出现减1现象。

2、原点(0,0)或(xSrc,ySrc)不是DIB图中第1 个像素,也不是最后1个像素,而是③,在图的左下角,即最后一行的第1个像素。

【Apollo11程序】

 效果图

/*------------------------------------------------------------
APOLLO11.C -- Program for screen captures
(c) Charles Petzold, 1998
------------------------------------------------------------*/ #include <windows.h>
#include "..\\DibHeads\\DibFile.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); static TCHAR szAppName[] = TEXT("Apollo11");
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
HWND hwnd;
MSG msg;
WNDCLASSEX wndclass; 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 = NULL;
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("Apollo 11"), // 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); while (GetMessage(&msg, NULL, , ))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
} LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
static BITMAPFILEHEADER* pbmfh[];
static BITMAPINFO* pbmi[];
static BYTE* pBits[];
static int cxClient, cyClient, cxDib[], cyDib[]; switch (message)
{
case WM_CREATE:
pbmfh[] = DibLoadImage(TEXT("Apollo11.bmp"));
pbmfh[] = DibLoadImage(TEXT("ApolloTD.bmp"));
if (pbmfh[] == NULL || pbmfh[] == NULL)
{
MessageBox(hwnd, TEXT("Cannot load DIB file"), szAppName, );
return ;
} //获得信息头和像素位指针
pbmi[] = (BITMAPINFO*)(pbmfh[] + );
pbmi[] = (BITMAPINFO*)(pbmfh[] + ); pBits[] = (BYTE*)pbmfh[] + pbmfh[]->bfOffBits;
pBits[] = (BYTE*)pbmfh[] + pbmfh[]->bfOffBits; //获取图像大小(为方便,这里只处理BITMAPINFOHEADER结构的DIB)
cxDib[] = pbmi[]->bmiHeader.biWidth;
cyDib[] = abs(pbmi[]->bmiHeader.biHeight); //绝对值! cxDib[] = pbmi[]->bmiHeader.biWidth;
cyDib[] = abs(pbmi[]->bmiHeader.biHeight); //绝对值!
return ; case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return ; case WM_PAINT:
hdc = BeginPaint(hwnd, &ps); //从下到上DIB整图显示
SetDIBitsToDevice(hdc,
,
cyClient / , //yDst
cxDib[], //整幅图宽度
cyDib[], //整幅图高度
,
,
, //第一扫描线
cyDib[], //扫描线数量
pBits[],
pbmi[],
DIB_RGB_COLORS); //从下到上DIB局部图显示
SetDIBitsToDevice(hdc,
,
cyClient / , //yDst
, //图的局部(宽度)
, //图的局部(高度)
, //源的X坐标,在图左下角的附近
, //源的Y坐标,在图左下角附近
, //第一扫描线
cyDib[], //扫描线数量
pBits[],
pbmi[],
DIB_RGB_COLORS); //从上到下DIB整图显示
SetDIBitsToDevice(hdc,
,
cyClient / , //yDst
cxDib[], //整幅图宽度
cyDib[], //整幅图高度
,
,
, //第一扫描线
cyDib[], //扫描线数量
pBits[],
pbmi[],
DIB_RGB_COLORS); //从上到下DIB局部图显示
SetDIBitsToDevice(hdc,
,
cyClient / , //yDst
, //图的局部(宽度)
, //图的局部(高度)
, //源的X坐标,在图左下角的附近
, //源的Y坐标,在图左下角附近
, //第一扫描线
cyDib[], //扫描线数量
pBits[],
pbmi[],
DIB_RGB_COLORS); EndPaint(hwnd, &ps);
return ; case WM_DESTROY:
PostQuitMessage();
return ;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
 //DibFile.h和DibFile.C文件见【ShowDib1程序】

15.2.4 顺序显示——扫描线

(1)SetDIBitsToDevice扫描线的工作原理

SetDIBitsToDevice(hdc,xDst,yDst,cxSrc,cySrc,xSrc,ySrc,yScan,cyScans,pBits,fClrUse);

  ①根据xSrc,ySrc,cxSrc,cySrc确定要显示的源矩形的范围(如图1),再根据xDst,yDst,cxSrc,cySrc确定DIB图像在逻辑坐标系中的输出位置和范围(如图2,用红色虚线框表示的矩形范围)。

  ②为pBits所在数据块按像素行划分出若干条扫描线第1行(也称为第一扫描线)编号为yScan号(一般为0,但这里为了更具普遍性,假设yScan等于20,即第1条扫描线编号为20号),第2条为21号,第3条为22号,以此类推……。直到pBits所有的像素行(或叫扫描线)都编号完毕。本例中DIB位图的高度为240,所以最后一行编号为20+240,即260号。

  ③开始扫描,此时当前扫描线会从A扫描到B。由图中可知,它将扫过从编号60到240的之间范围。假设当前的扫描位置是在编号为70的绿线上。

  ④当在图1中确定好当前扫描线编号以后,再根据当前扫描线的位置,计算出在逻辑坐标系中的输出位置(假设在图2中的绿线位置),而该处输出的数据来自于pBits中扫描线被编号为70号的那行数据,即pBits中第90行的数据。

  ⑤继续扫描其他行,直至AB间的所有像素行都扫描完毕,即结束。

【注意】

  ①本例中,pBits像素的扫描线编号(20-260),但源矩形中只要求输出编号为60至240号的扫描行数据。也就是说,pBits中第40行至220行的数据。所以最终结果如图2所示(要特别注意,源和目标中,显示的图像己经不同了(见红色虚线框内的内容),主要原因是我们将pBits的第1行编号为20,如果编为0(即yScan=0)则显示的内容就会完全相同)。

  ②由于pBits扫描线编号在20-260之间,所以如果当前扫描线要扫描图1中y轴20以下的那些范围,则在pBits中会因找不到对应的扫描线,从而导致那部分的数据在逻辑坐标系中会显示为空白

(2)SetDIBitsToDevice实例分析

【SeqDisp程序】
效果图

/*------------------------------------------------------------
SEQDISP.C -- Sequential Display of DIBs
(c) Charles Petzold, 1998
------------------------------------------------------------*/ #include <windows.h>
#include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static TCHAR szAppName[] = TEXT("SeqDisp"); 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 Sequential 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;
} LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
static BITMAPINFO* pbmi;
static BYTE* pBits;
static int cxDib, cyDib, cBits;
static OPENFILENAME ofn;
static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
static TCHAR szFilter[] = TEXT("Bitmap Files(*.BMP)\0*.bmp\0")\
TEXT("All Files(*.*)\0*.*\0\0"); BITMAPFILEHEADER bmfh;
BOOL bSuccess, bTopDown;
DWORD dwBytesRead;
HANDLE hFile;
int iInfoSize, iBitsSize, iRowLength; switch (message)
{
case WM_CREATE:
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.hInstance = NULL;
ofn.lpstrFilter = szFilter;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = ;
ofn.nFilterIndex = ;
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFileTitle = szTitleName;
ofn.nMaxFileTitle = MAX_PATH;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = NULL;
ofn.Flags = ; //在打开和关闭函数中设置
ofn.nFileOffset = ;
ofn.nFileExtension = ;
ofn.lpstrDefExt = TEXT("bmp"); //默认扩展名
ofn.lCustData = ;
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
return ; case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDM_FILE_OPEN: //显示打开文件对话框
if (!GetOpenFileName(&ofn))
return ; //清除之前打开的位图文件
if (pbmi)
{
free(pbmi);
pbmi = NULL;
} if (pBits)
{
free(pBits);
pBits = NULL;
} //擦掉客户区上的位图
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd); //可注释掉看下 //打开文件
hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hFile == INVALID_HANDLE_VALUE)
{
MessageBox(hwnd, TEXT("Cannot open file."), szAppName, MB_ICONWARNING | MB_OK);
return ;
} //读取BITMAPFILEHEADER
bSuccess = ReadFile(hFile, &bmfh, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL); if (!bSuccess || dwBytesRead != sizeof(BITMAPFILEHEADER))
{
MessageBox(hwnd, TEXT("Cannot open file."), szAppName, MB_ICONWARNING | MB_OK);
CloseHandle(hFile);
return ;
} //检验是否是位图文件,第1-2个字节为“BM”
if (bmfh.bfType != *(WORD*)"BM")
{
MessageBox(hwnd, TEXT("File is not a bitmap."), szAppName, MB_ICONWARNING | MB_OK);
CloseHandle(hFile);
return ;
} //为文件信息头和像素位数据分配内存
iInfoSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
iBitsSize = bmfh.bfSize - bmfh.bfOffBits; pbmi = malloc(iInfoSize);
pBits = malloc(iBitsSize); if (pbmi == NULL || pBits == NULL)
{
MessageBox(hwnd, TEXT("Cannot allocate memory."), szAppName, MB_ICONWARNING | MB_OK);
if (pbmi)
{
free(pbmi);
pbmi = NULL;
} if (pBits)
{
free(pBits);
pBits = NULL;
} CloseHandle(hFile);
return ;
} //读取信息头
bSuccess = ReadFile(hFile, pbmi, iInfoSize, &dwBytesRead, NULL);
if (!bSuccess || iInfoSize != dwBytesRead)
{
MessageBox(hwnd, TEXT("Cannot allocate memory."), szAppName, MB_ICONWARNING | MB_OK);
if (pbmi)
{
free(pbmi);
pbmi = NULL;
} if (pBits)
{
free(pBits);
pBits = NULL;
} CloseHandle(hFile);
return ;
} //获取像素数据和高度
bTopDown = FALSE;
if (pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
cxDib = ((BITMAPCOREHEADER*)pbmi)->bcWidth;
cyDib = ((BITMAPCOREHEADER*)pbmi)->bcHeight;
cBits = ((BITMAPCOREHEADER*)pbmi)->bcBitCount;
} else
{
bTopDown = (pbmi->bmiHeader.biHeight < ); cxDib = pbmi->bmiHeader.biWidth;
cyDib = abs(pbmi->bmiHeader.biHeight);
cBits = pbmi->bmiHeader.biBitCount; if (pbmi->bmiHeader.biCompression != BI_RGB && pbmi->bmiHeader.biCompression != BI_BITFIELDS)
{
MessageBox(hwnd, TEXT("File is compressed."), szAppName, MB_ICONWARNING | MB_OK);
if (pbmi)
{
free(pbmi);
pbmi = NULL;
} if (pBits)
{
free(pBits);
pBits = NULL;
} CloseHandle(hFile);
return ;
}
} //计算每行像素宽度,4的倍数
iRowLength = ((cxDib*cBits + )& ~) >> ; //显示位图
SetCursor(LoadCursor(NULL, IDC_WAIT));
ShowCursor(TRUE); hdc = GetDC(hwnd); for (int y = ; y < cyDib; y++)
{
ReadFile(hFile, pBits + y*iRowLength, iRowLength, &dwBytesRead, NULL);
/*
1、每次扫描时,源矩形0,y,cxDib,cyDib-y,目标矩形0,0,cxDib,cyDib-y
2、每次调用函数时,像素的数据在改变,pBits+y*iRowLength;
3、每次都为像素位的第一行数据编号为y或cyDib-y-1
*/
SetDIBitsToDevice(hdc,
, //xDst
, //yDst
cxDib, //cxSrc
cyDib - y, //cySrc,课本这里为cyDib。
, //xSrc
y, //ySrc,课本这里为0,这两处的更改,效率更高
bTopDown ? cyDib - y - : y, //给第一行扫描行编号
, //每次扫描一行
pBits + y*iRowLength, //第一行扫描行的数据
pbmi,
DIB_RGB_COLORS);
} ReleaseDC(hwnd, hdc);
CloseHandle(hFile);
SetCursor(LoadCursor(NULL, IDC_ARROW));
ShowCursor(FALSE); return ;
}
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
if (pbmi && pBits)
{
SetDIBitsToDevice(hdc,
, //xDst
, //yDst
cxDib, //cxSrc
cyDib, //cySrc
, //xSrc
, //ySrc
, //第一行扫描行编号
cyDib,
pBits,
pbmi,
DIB_RGB_COLORS);
}
EndPaint(hwnd, &ps);
return ; case WM_DESTROY:
if (pbmi) free(pbmi); if (pBits) free(pBits); PostQuitMessage();
return ;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}

//resouce.h

//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by SeqDisp.rc
//
#define IDM_FILE_OPEN 40001 // Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40002
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

//SeqDisp.rc

//Microsoft Developer Studio generated resource script.
//
#include "resource.h" #define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h" /////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS /////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32 #ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
// TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END #endif // APSTUDIO_INVOKED /////////////////////////////////////////////////////////////////////////////
//
// Accelerator
// SEQDISP ACCELERATORS DISCARDABLE
BEGIN
"O", IDM_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT
END /////////////////////////////////////////////////////////////////////////////
//
// Menu
// SEQDISP MENU DISCARDABLE
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Open...\tCtrl+O", IDM_FILE_OPEN
END
END #endif // English (U.S.) resources
///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
// /////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

15.2.5 拉伸到合适大小

(1)StretchDIBits函数说明

参数

说明

hdc

设备环境句柄

xDst

目标x坐标

yDst

目标y坐标

cxDst

目标图像的像素宽度(字节),可正可负,实现翻转

cyDst

目标图像的像素高度(字节),可正可负,实现翻转

xSrc

源x坐标(有符号)

ySrc

源y坐标

cxSrc

源图像的像素宽度(字节),可正可负,实现翻转

cySrc

源图像的像素高度(字节),可正可负,实现翻转

pBits

像素位数据

fClrUse

使用颜色标记:DIB_PAL_COLORS或DIB_RGB_COLORS

dwRop

光栅操作

(2)StretchDIBits坐标说明

源矩形

目标矩形

①(xSrc,ySrc)—内存中第一个像素!

①(xDst,yDst+cyDst-1)

②(xSrc+cxSrc-1,ySrc)

②(xDst+cxDst-1,yDst+cyDst-1)

③(xSrc,ySrc+cySrc-1)

③(xDst,yDst)

④(xSrc+cxSrc-1,ySrc+cySrc-1)—内存最后1个像素

④(xDst+cxDst-1,yDst)

注意:1、右列式子出现减1并不准确,因为拉伸和映射模式的影响。

2、原点(0,0)位于DIB图的左下角(左图中的①),第一行的第1个像素。

(3)判断图像是否上下翻转或左右翻转

if(!Sign(xMM*cxSrc*cxDst))

DIB沿垂直轴翻转(镜像)

1、xMM为映射模式x从左到右增加,取1,相反取-1。

2、yMM为映射模式y从上到下增加,取1,相反取-1。

if(!Sign(yMM*cySrc*cyDst))

DIB沿水平轴翻转(上下翻转)

【ShowDib2程序】

/*------------------------------------------------------------
SHOWDIB2.C -- Shows a DIB in the client area
(c) Charles Petzold, 1998
------------------------------------------------------------*/ #include <windows.h>
#include "resource.h"
#include "..\\ShowDib1\\DibFile.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); static TCHAR szAppName[] = TEXT("ShowDib2");
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("Show DIB #2"), // 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;
} int ShowDib(HDC hdc, BITMAPINFO* pbmi, BYTE* pBits, int cxDib, int cyDib, int cxClient, int cyClient, WORD wShow)
{
switch (wShow)
{
case IDM_SHOW_NORMAL: //正常显示
return SetDIBitsToDevice(hdc, , , cxDib, cyDib, , , , cyDib, pBits, pbmi, DIB_RGB_COLORS); case IDM_SHOW_CENTER: //居中显示
return SetDIBitsToDevice(hdc, (cxClient - cxDib) / ,
(cyClient - cyDib) / ,
cxDib, cyDib, , ,
, cyDib, pBits, pbmi, DIB_RGB_COLORS);
case IDM_SHOW_STRETCH: //拉伸到整个客户区
SetStretchBltMode(hdc, COLORONCOLOR); //缩小时,直接去掉颜色值
return StretchDIBits(hdc, , , cxClient, cyClient,
, , cxDib, cyDib,
pBits, pbmi, DIB_RGB_COLORS, SRCCOPY);
case IDM_SHOW_ISOSTRETCH:
SetStretchBltMode(hdc, COLORONCOLOR);
SetMapMode(hdc, MM_ISOTROPIC);
SetWindowExtEx(hdc, cxDib, cyDib, NULL);
SetViewportExtEx(hdc, cxClient, cyClient, NULL);
SetWindowOrgEx(hdc, cxDib / , cyDib / , NULL);
SetViewportOrgEx(hdc, cxClient / , cyClient / , NULL); return StretchDIBits(hdc, , , cxDib, cyDib, //逻辑坐标系的范围
, , cxDib, cyDib,
pBits, pbmi, DIB_RGB_COLORS, SRCCOPY);
}
return ;
} LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BITMAPFILEHEADER* pbmfh;
static BITMAPINFO* pbmi;
static BYTE* pBits; static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
static int cxClient, cyClient, cxDib, cyDib;
HDC hdc, hdcPrn;
static DOCINFO di = { sizeof(DOCINFO), TEXT("ShowDib2:Printing") };
PAINTSTRUCT ps;
BOOL bSuccess;
int iEnable, cxPage, cyPage;
static WORD wShow = IDM_SHOW_NORMAL;
HMENU hMenu;
HGLOBAL hGlobal;
BYTE *pGlobal; static PRINTDLG printdlg = { sizeof(PRINTDLG) }; switch (message)
{
case WM_CREATE: DibFileInitialize(hwnd);
return ; case WM_INITMENUPOPUP:
if (pbmfh)
iEnable = MF_ENABLED;
else
iEnable = MF_GRAYED; EnableMenuItem((HMENU)wParam, IDM_FILE_SAVE, iEnable);
EnableMenuItem((HMENU)wParam, IDM_FILE_PRINT, iEnable);
EnableMenuItem((HMENU)wParam, IDM_EDIT_CUT, iEnable);
EnableMenuItem((HMENU)wParam, IDM_EDIT_COPY, iEnable);
EnableMenuItem((HMENU)wParam, IDM_EDIT_DELETE, iEnable);
return ; case WM_SIZE:
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return ; case WM_COMMAND:
hMenu = GetMenu(hwnd); switch (LOWORD(wParam))
{
case IDM_FILE_OPEN:
//显示打开对话框
if (!DibFileOpenDlg(hwnd, szFileName, szTitleName))
return ; //如果DIB文件己被载入,释放内存
if (pbmfh)
{
free(pbmfh);
pbmfh = NULL;
} //将整个DIB加载到内存中
SetCursor(LoadCursor(NULL, IDC_WAIT));
ShowCursor(TRUE); pbmfh = DibLoadImage(szFileName); ShowCursor(FALSE);
SetCursor(LoadCursor(NULL, IDC_ARROW)); //使客户区无效,以便后面的绘图并擦除以前客户区显示的内容
InvalidateRect(hwnd, NULL, TRUE); if (pbmfh == NULL)
{
MessageBox(hwnd, TEXT("Cannot load DIB file"), szAppName, );
return ;
} //获取指向DIB信息头的指针和指向像素位的指针
pbmi = (BITMAPINFO*)(pbmfh + );
pBits = (BYTE*)pbmfh + pbmfh->bfOffBits; //获取图像的宽度和高度
if (pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
cxDib = ((BITMAPCOREHEADER*)pbmi)->bcWidth;
cyDib = ((BITMAPCOREHEADER*)pbmi)->bcHeight;
} else
{
cxDib = pbmi->bmiHeader.biWidth;
cyDib = abs(pbmi->bmiHeader.biHeight);
}
return ; case IDM_FILE_SAVE: //显示保存对话框
if (!DibFileSaveDlg(hwnd, szFileName, szTitleName))
return ; //将DIB位图保存到文件中
SetCursor(LoadCursor(NULL, IDC_WAIT));
ShowCursor(TRUE); bSuccess = DibSaveImage(szFileName, pbmfh); ShowCursor(FALSE);
SetCursor(LoadCursor(NULL, IDC_ARROW)); if (!bSuccess)
MessageBox(hwnd, TEXT("Cannot save DIB file"), szAppName, );
return ; case IDM_FILE_PRINT:
if (!pbmfh)
return ; //获取打印机DC
printdlg.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION;
if (!PrintDlg(&printdlg))
return ;
hdcPrn = printdlg.hDC;
if (NULL == hdcPrn)
{
MessageBox(hwnd, TEXT("Cannot obtain Printer DC"),
szAppName, MB_ICONEXCLAMATION | MB_OK);
return ;
} //检查打印机是否可以打印位图
if (!(RC_BITBLT)&GetDeviceCaps(hdcPrn, RASTERCAPS))
{
DeleteDC(hdcPrn);
MessageBox(hwnd, TEXT("Printer cannot print bitmaps"),
szAppName, MB_ICONEXCLAMATION | MB_OK);
return ;
} //获得可打印区域的大小
cxPage = GetDeviceCaps(hdcPrn, HORZRES);
cyPage = GetDeviceCaps(hdcPrn, VERTRES); bSuccess = FALSE; //将位图输程打印机
SetCursor(LoadCursor(NULL, IDC_WAIT));
ShowCursor(TRUE);
//StartDoc、StartPage、EndPage、EndDoc返回值>0说明执行成功。
if ((StartDoc(hdcPrn, &di)>) && (StartPage(hdcPrn)>))
{
ShowDib(hdcPrn, pbmi, pBits, cxDib, cyDib, cxPage, cyPage, wShow);
if (EndPage(hdcPrn)>)
{
bSuccess = TRUE;
EndDoc(hdcPrn);
}
}
ShowCursor(FALSE);
SetCursor(LoadCursor(NULL, IDC_ARROW));
DeleteDC(hdcPrn);
if (!bSuccess)
MessageBox(hwnd, TEXT("Could not print bitmap"),
szAppName, MB_ICONEXCLAMATION | MB_OK);
return ; case IDM_EDIT_COPY:
case IDM_EDIT_CUT:
if (!pbmfh)
return ; //生成一个紧凑型DIB
hGlobal = GlobalAlloc(GHND | GMEM_SHARE,
pbmfh->bfSize - sizeof(BITMAPFILEHEADER));
pGlobal = GlobalLock(hGlobal);
CopyMemory(pGlobal, (BYTE*)pbmfh + sizeof(BITMAPFILEHEADER),
pbmfh->bfSize - sizeof(BITMAPFILEHEADER));
GlobalUnlock(hGlobal); //传输到剪贴板
OpenClipboard(hwnd);
EmptyClipboard();
SetClipboardData(CF_DIB, hGlobal);
CloseClipboard(); if (LOWORD(wParam) == IDM_EDIT_COPY)
return ;
//IDM_EDIT_CUT则继续执行下去 case IDM_EDIT_DELETE:
if (pbmfh)
{
free(pbmfh);
pbmfh = NULL;
InvalidateRect(hwnd, NULL, TRUE);
} return ; case IDM_SHOW_CENTER:
case IDM_SHOW_ISOSTRETCH:
case IDM_SHOW_NORMAL:
case IDM_SHOW_STRETCH:
CheckMenuItem(hMenu, wShow, MF_GRAYED);
wShow = LOWORD(wParam);
CheckMenuItem(hMenu, wShow, MF_CHECKED);
InvalidateRect(hwnd, NULL, TRUE);
return ;
}
break; case WM_PAINT:
hdc = BeginPaint(hwnd, &ps); if (pbmfh)
{
ShowDib(hdc, pbmi, pBits, cxDib, cyDib, cxClient, cyClient, wShow);
} EndPaint(hwnd, &ps);
return ; case WM_DESTROY:
if (pbmfh)
free(pbmfh);
PostQuitMessage();
return ;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}

//resource.h

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 ShowDib2.rc 使用
//
#define IDM_FILE_OPEN 40001
#define IDM_FILE_SAVE 40002
#define IDM_FILE_PRINT 40003
#define IDM_EDIT_CUT 40004
#define IDM_EDIT_COPY 40005
#define IDM_EDIT_CLEAR 40006
#define IDM_EDIT_DELETE 40007
#define IDM_SHOW_NORMAL 40008
#define IDM_SHOW_CENTER 40009
#define IDM_SHOW_STRETCH 40010
#define IDM_SHOW_ISOSTRETCH 40011
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40028
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

//ShowDib2.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
//
SHOWDIB2 MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Open...\tCtrl+O", IDM_FILE_OPEN
MENUITEM "&Save...\tCtrl+S", IDM_FILE_SAVE
MENUITEM SEPARATOR
MENUITEM "&Print\tCtrl+P", IDM_FILE_PRINT
END
POPUP "&Edit"
BEGIN
MENUITEM "Cu&t\tCtrl+X", IDM_EDIT_CUT
MENUITEM "&Copy\tCtrl+C", IDM_EDIT_COPY
MENUITEM "&Delete\tDelete", IDM_EDIT_DELETE
END
POPUP "&Show"
BEGIN
MENUITEM "&Actual Size", IDM_SHOW_NORMAL, CHECKED
MENUITEM "&Center", IDM_SHOW_CENTER
MENUITEM "&Stretch toWindow", IDM_SHOW_STRETCH
MENUITEM "Stretch &Isotropically ", IDM_SHOW_ISOSTRETCH
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
SHOWDIB2 ACCELERATORS
BEGIN
"^O", IDM_FILE_OPEN, ASCII, NOINVERT
"^S", IDM_FILE_SAVE, ASCII, NOINVERT
"^P", IDM_FILE_PRINT, ASCII, NOINVERT
"^C", IDM_EDIT_COPY, ASCII, NOINVERT
VK_DELETE, IDM_EDIT_DELETE, VIRTKEY, SHIFT, NOINVERT
"^X", IDM_EDIT_CUT, ASCII, NOINVERT
END
#endif // 中文(简体,中国) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

//DibFile.h和DibFile.c见ShowDib1程序

第15章 设备无关位图_15.2 显示和打印DIB的更多相关文章

  1. 第15章 设备无关位图_15.3 DIB和DDB的结合

    第15章 设备相关位图_15.3 DIB和DDB的结合 15.3.1 从DIB创建DDB (1)hBitmap =CreateDIBitmap(…)——注意这名称会误导,实际上创建的是DDB 参数 说 ...

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

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

  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. JavaScript实战(带收放动画效果的导航菜单)

    虽然有很多插件可用,但为了共同提高,我做了一系列JavaScript实战系列的实例,分享给大家,前辈们若有好的建议,请务必指出,免得误人子弟啊! ( 原创文章,转摘请注明:苏福:http://www. ...

  2. SharePoint 使用脚本为表单绑定事件

    在SharePoint的使用过程中,我们经常需要为表单页面做一些特殊处理,比如说新建页面的时候有多选项的字段,但是只能选择指定数量的选项,尤其在新闻列表或者调查列表等特殊场景中,广泛使用. 下面,我们 ...

  3. 对tableView三种计算动态行高方法的分析

    tableView是一个神奇的东西,可以这么说,就算是一个初学者如果能把tableView玩的很6,那编一般的iOS的需求都问题不大了.tableView是日常开发中用烂了的控件,但是关于tableV ...

  4. 你真的了解UIViewController生命周期吗?

    一:首先了解一下生命周期图 二:UIViewController 生命周期介绍 1.通过alloc init 分配内存,初始化controller. 2.loadView loadView方法默认实现 ...

  5. 怎么查看Mac电脑的开机记录?

    可以使用last命令查看Mac电脑来看开机记录,同时也能查看关机记录. 首先打开mac的命令终端: 命令行终端敲入命令:last | grep reboot (查看开机时间记录) 命令行终端敲入命令: ...

  6. 【代码笔记】iOS-点击任何处,出现城市

    一,效果图. 二,工程目录. 三,代码. //点击任何处,出现城市 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { ...

  7. 【代码笔记】iOS-3DES+Base64加密解密

    一,工程目录. 二,代码. RootViewController.m #import "RootViewController.h" #import "NSString+T ...

  8. 使用eclipse创建spring mvc web工程并部署

    创建maven工程

  9. 使用 PHPMailer 发送邮件

    转载 http://blog.csdn.net/liruxing1715/article/details/7914974 PHPMailer 的官方网站:http://phpmailer.worxwa ...

  10. MyEclipse、Eclipse优化设置

    第一步: 取消自动validation validation有一堆,什么xml.jsp.jsf.js等等,我们没有必要全部都去自动校验一下,只是需要的时候才会手工校验一下! 取消方法: windows ...