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. 微信网页授权(OAuth2.0) PHP 源码简单实现

    提要: 1. 建议对OAuth2.0协议做一个学习. 2. 微信官方文档和微信官网工具要得到充分利用. 比较简单,直接帖源代码了.其中“xxxxxxxxxx”部分,是需要依据自己环境做替换的 /** ...

  2. github-ssh

        # lsb_release -a    No LSB modules are available.    Distributor ID:    Ubuntu    Description:   ...

  3. IOS开发--微信支付

    前言:下面介绍微信支付的开发流程的细节,图文并茂,你可以按照我的随笔流程过一遍代码.包你也学会了微信支付.而且支付也是面试常问的内容. 正文: 1.首先在开始使用微信支付之前,有一些东西是开发者必须要 ...

  4. JavaBean的作用域

    JavaBean的作用域 scope属性决定了JavaBean对象存在的范围. scope的可选值包括四种: page(默认值) request session application 这四个值对应的 ...

  5. Android自定义控件1--自定义控件介绍

    Android控件基本介绍 Android本身提供了很多控件比如我们常用的有文本控件TextView和EditText:按钮控件Button和ImageButton状态开关按钮ToggleButton ...

  6. clang -rewrite-objc的使用点滴

    ➠更多技术干货请戳:听云博客 clang -rewrite-objc的作用是把oc代码转写成c/c++代码,我们常用它来窥探OC的一些秘密. 1.最简单的例子 main.m的代码如下: int mai ...

  7. 【代码笔记】iOS-将log日志保存到文件

    代码: #import "AppDelegate.h" #import "RootViewController.h" @implementation AppDe ...

  8. 【代码笔记】iOS-给UIImageView加上圆角效果

    一,效果图. 二,代码. RootViewController.m #import "RootViewController.h" @interface RootViewContro ...

  9. Swift 二维码扫描 简单实现

    3.30看视频  学到了二维码简单的实现 还有一些动画的实现  今天就先记录一下二维码扫描的简单实现  不太好记手写一遍 学习的基础在于模仿嘛 创建一个实现二维码扫描的步骤 1.首先是懒加载创建 会话 ...

  10. 基于 LocalAuthentication 框架的指纹解锁

    效果 想必大家对 iPhone 的指纹解锁功能已经相当的熟悉了.来看看效果吧! Local Authentication 概述 Local Authentication 框架提供了按照指定的安全策略请 ...