第15章 设备无关位图_15.2 显示和打印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
(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);
- }
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的更多相关文章
- 第15章 设备无关位图_15.3 DIB和DDB的结合
第15章 设备相关位图_15.3 DIB和DDB的结合 15.3.1 从DIB创建DDB (1)hBitmap =CreateDIBitmap(…)——注意这名称会误导,实际上创建的是DDB 参数 说 ...
- 第15章 设备无关位图_15.1 DIB文件格式
15.1 DIB文件格式(一种文件格式,扩展名为BMP) 15.1.1 OS/2风格的DIB 文件格式 字段 说明 文件头 (BITMAPFILEHEADER) 1.共14个字节 2.缩写建议用bmf ...
- device-independent bitmap (DIB) 设备无关位图
设备无关位图即独立于设备的位图(DIB)与"Device-Dependent Bitmaps (DDB) 设备相关位图"相比,它不再依赖于具体的设备,从而更适合在不同的计算机之间传 ...
- windows设备相关位图与设备无关位图
windows支持两种位图格式,DDB(device-dependent bitmap),DIB(device-independent bitmap).设备相关位图用于windows显示系统中,其图像 ...
- Device-Dependent Bitmaps (DDB) 设备相关位图
设备相关的位图(DDB)使用单一结构BITMAP结构描述.该结构的成员指定矩形区域的宽度和高度,以像素为单位;将条目从设备调色板映射到像素的数组的宽度;以及器件的颜色格式,在每个像素的颜色平面和位数方 ...
- ASM:《X86汇编语言-从实模式到保护模式》第15章:任务切换
15章其实应该是和14章相辅相成的(感觉应该是作者觉得14章内容太多了然后切出来了一点).任务切换和14章的某些概念是分不开的. ★PART1:任务门与任务切换的方法 1. 任务管理程序 14章的时候 ...
- Linux就这个范儿 第15章 七种武器 linux 同步IO: sync、fsync与fdatasync Linux中的内存大页面huge page/large page David Cutler Linux读写内存数据的三种方式
Linux就这个范儿 第15章 七种武器 linux 同步IO: sync.fsync与fdatasync Linux中的内存大页面huge page/large page David Cut ...
- unix network programming(3rd)Vol.1 [第13~15章]《读书笔记系列》
第13章 守护进程和inetd 超级服务器 syslog() daemon_init() setuid() setgid() 第14章 高级IO 标准I/O函数库,支持3种缓冲 缓冲(读写存储设备(硬 ...
- 【RL-TCPnet网络教程】第15章 RL-TCPnet之创建多个TCP连接
第15章 RL-TCPnet之创建多个TCP连接 本章节为大家讲解RL-TCPnet的TCP多客户端实现,因为多客户端在实际项目中用到的地方还挺多,所以我们也专门开启一个章节做讲解.另外,学习 ...
随机推荐
- HTML中tr标签设置边框不显示的解决办法
今天在操作表格的时候发现设置表格中行的边框没有显示,然后自己新建了一个表格发现确实不显示 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Tr ...
- arcgis engine 调用arcgis server服务
首先需要添加两个引用: using ESRI.ArcGIS.GISClient;using ESRI.ArcGIS.DataSourcesRaster; /// <summary> /// ...
- SharePoint Online 创建门户网站系列之创建栏目
前 言 SharePoint Online的栏目,简单描述即显示在首页上的各个模块信息,这里,我们主要介绍我们首页上的栏目,包括简介类型.新闻列表类型.图片类型: 下面,让我们开始在SharePoin ...
- 如何保护在Autodesk应用程序商店的应用不被盗版 - 1
Autodesk应用程序商店如火如荼,但来自中国的应用却还是寥寥无几.大家在担心什么呢?可能其中一个因素就是担心自己的应用上线后被盗版的问题.对应用的版权保护和授权管理是每个应用开发者都应该认真考虑的 ...
- 通过API找出Autodesk Vault中某个用户组可以访问的Vault
首先在Vault Explorer中可以这样查看和更改某个用户组有权访问的vault Tools –> Administration –> Global Settings –> Gr ...
- Xcode中XVim的常用操作
- Hbase Java API详解
HBase是Hadoop的数据库,能够对大数据提供随机.实时读写访问.他是开源的,分布式的,多版本的,面向列的,存储模型. 在讲解的时候我首先给大家讲解一下HBase的整体结构,如下图: HBase ...
- iOS runtime的理解和应用
项目中经常会有一些的功能模块用到runtime,最近也在学习它.对于要不要阅读runtime的源码,我觉得仅仅是处理正常的开发,那真的没有必要,只要把常用的一些函数看下和原理理解下就可以了. 但是如果 ...
- android deep link(深度链接)与自定义协议!
此自定义仅供参考! 首先打开androidManifest.xml 在MainActivity中添加如下内容: <activity android:name=".MainActivit ...
- 访客至上的Web、移动可用性设计--指导原则
文章出自:听云博客 关于可用性设计,之前写过一个“纸上谈兵”版本的,那篇帖子主要是根据A/B test的方式来进行的. 但是最近找了本Steve krug写的Don't make me think,我 ...