VC+ + 视图内容导出成位图的方法
张 弦, 鲍征宇
(中国地质大学地球化学研究所, 武汉 430074)
摘 要: 为了获得程序视图的内容, 我们多采用屏幕硬拷贝的方法, 在视图内容较多, 需要滚屏显示的时候, 这种方法尤其费时费力, 且在图形拼合时易产生偏差。作者在本文中介绍了在VC+ + 编程中直接把视图内容导出成位图文件的方法, 阐述了基本原理, 并提供了源代码。
关键词: 位图; 导出; VC+ + ; 图形图像; 文档/视图
Microsoft Visual C+ + 6. 0 是Windows 操作系统中程序设计的利器, 并有强大的图形图像编程能力。在进行数值图像处理(如遥感图像处理、岩矿显微组构的数值图像分析等) 时, 常用VC+ + 作为编程工具,程序运行结果多以图形(如: 直方图、等值线图、曲线图、以符号描述的目标物体分布图)、图像(如岩石显微图像的矿物边界的圈定及目标物体的分割) 的形式呈现。为了保存程序视图的内容, 我们平时多用的是屏幕拷贝再粘贴至其它图像处理软件(如: Photoshop) 中。编辑保存成图像文件的方法, 不能实现程序本身把视图内容导出成图像的功能, 在保存视图内容时不方便, 尤其是在视图内容较多, 需要滚屏显示时, 要分次
对屏幕进行硬拷贝, 再采用图像处理软件进行裁剪、拼合的方法, 费时费力, 而且多个小图像拼合成一个大图像时也存在偏差。作者在文中介绍了把视图内容(全部或局部) 直接导出成位图文件的方法, 易于编程实现。
1 基本原理
Windows系统中有两种类型的位图: 设备相关位图(Device Dependent Bitmap, 简称DDB) 和设备无关位图(Device Independent Bitmap, 简称DIB)。DDB 是一种内部位图格式, 它们在内存中的结构和位置依赖于管理它们的设备驱动程序, 显示的图像依计算机显示系统的不同而不同, 因此, 一般不存储为文件。与DDB 相比, D IB 是一种外部的位图格式, 文件的结构与计算机系统硬件无关, 因此, 在不同的显示系统中具有相同的显示结果, 常存储为以. bmp 为后缀的文件。
Ms VC+ + 6.0 基于Document/View 结构的程序中, 由视图类的OnDraw(CDC* pDC) 函数在窗口客户区中显示文字、图形、图像等视图内容。位图的显示就是把位图显示在屏幕上, 其反过程就是在截取屏幕的指定区域内放入位图。显示一幅D IB 位图图像的方法之一是先把D IB 位图转换成DDB 位图bmp, 再把bmp 位图选入设备绘图环境(Device Context) 中pDC2>SelectObject (&bmp) , 调用BitBlt () 函数画至显示屏, 即可完成位图的显示。DDB 位图选入设备绘图环境后, 在设备环境没有选入新的绘图对象之前, 其视图内容就与DDB 位图的内容一致。我们可以通过更改视图内容来更改被选入设备绘图环境的DDB 位图。
这样就可以获得视图的DDB 位图, 再把DDB 转换成D IB, 完成D IB 位图的保存即可。
2 实现代码详解
211 DDB 位图的生成与视图内容的获取
以下的代码要加入到视图类的成员函数中。
CBitmap bmp; //用于保存视图的内容的DDB 位图
CDC memDC; //与当前显示设备相兼容的内存设备环境
CSize sizeTotal= GetTotalSize () ; //获取全部视图的大小, 在这里可以通过
//指定sizeTotal 来获取视图中特定的区域
int nMemDC; //保存显示设备环境, 用于恢复初始设备环境
nMapMode= MM-LOENGLISH; //显示模式, MM-LOENGLISH
int bits= GetDC()->GetDeviceCaps(BITSPIXEL )*GetDC()->GetDeviceCaps(PLANES);
//获取显示设备的颜色表位数
bmp.CreateBitmap( sizeTotal.cx, sizeTotal.cy, 1, bits, NULL ) ; //创建DDB 视图, 大小由sizeTotal 来指定
memDC.CreateCompatibleDC(GetDC() ) ; //创建兼容的内存设备环境
nMemDC= memDC.SaveDC() ; //保存设备环境的初始状态
memDC.SelectObject(&bmp) ; //把DDB 位图选入绘图设备
memDC.FillSolidRect(0, 0, sizeTotal. cx, sizeTotal. cy, GetDC()->GetBkColor () ) ;
//以当前视图的背景色来填充位图(初始化位图)
memDC.SetMapMode(nMapMode) ;
OnDraw(&memDC) ; //完成视图内容的获取
memDC.RestoreDC(nMemDC) ; //恢复至设备环境的初始状态
212 DDB 位图转换成D IB 位图
由于D IB 图像的每行都被填充到一个四字节边界, 因此需要经常计算其每行所实际占用的倍数。宏WIDTHBYTE 将一个数对齐于四字节边界, 可方便地用于计算D IB 行的长度, 定义如下:
#define WIDTHBYTES(bits) ( ( ( (bits) + 31)/ 32) 3 4)
// pBmp 是传递过来的要转换的DDB 位图的指针, pDC 为显示设备环境的指针
//函数返回DIB 位图的句柄
//全局函数
HGLOBAL ConvertDDB2D IB (CBitmap* pBmp, CDC3 pDC)
{
BITMAPINFOHEADER bi; //DIB 位图信息头
LPBITMAPINFO lpBi; //DIB 位图信息指针
BITMAP bm;
DWORD dwSizeCT;
DWORD dwDibL en;
HGLOBAL hData;
pBmp2> GetBitmap(&bm) ; //获得B ITMA P 结构
bi.biSize= sizeof (BITMAPINFOHEADER);
bi.biW idth= bm.bmW idth;
bi.biHeight= bm.bmHeigh t;
bi.biP lanes= bm.bmPlanes;
bi.biBitCount= bm. bmPlanes* bm.bmBitsPixel;
bi.biSize Image= 0;
bi.biXPelsPerM eter= 0;
bi.biYPelsPerM eter= 0;
bi.biComp ression= B I- RGB;
bi.biClrUsed= 0;
bi.biClrImportant= 0;
switch (bi. biB itCoun)
{
case 1: {dwSizeCT= 2; break; }
case 4: {dwSizeCT= 16; break; }
case 8: {dwSizeCT= 256; break; }
case 24: {dwSizeCT= 0; break; }
default: {dwSizeCT= 0; }
}
dwDibL en= bi.biSize+ dwSizeCT* sizeof(RGBQUAD) ;
hData= ::GlobalAlloc(GHND, dwDibLen) ;
lpBi= (LPBITMAPINFO) ::GlobalLock(hData);
lpBi2>bmiHeader= bi;
//获得DIB 位图文件信息, 即为lpBi赋值
VERIFY
(
::GetDIBits
(
pDC2>GetSafeHdc() ,
(HBITMAP)pBmp2>GetSafeHandle() ,
0,(WORD)bi.biHeight,
NULL ,
lpBi,
DIB- RGB- COLORS
)
) ;
DWORD dwErr;
dwErr= GetLastError () ;
bi= lpBi2>bmiHeader; //获得D IB 位图信息头
::GlobalUnlock(hData) ;
//计算位图大小( inbytes)
if (! bi.biSizeImage)
{
bi.biSizeImage= WIDTHBYTES (bi.biBitCount* bi. biWidth) *bi.biHeight;
}
dwDibLen+ = bi.biSizeImage;
hData= ::GlobalReAlloc(hData, dwDibLen, CHND) ;
ASSERT (hData) ;
lpBi= (LPBITMAPIN FO) ::GlobalLock(hData) ;
ASSERT ( lpBi) ;
//复制DDB 位图内容到DIB 位图
V ER IFY
(
::GetDIBits
(
pDC->GetSafeHdc(),
(HBITMAP)pBmp->GetSafeHandle() ,
0,
(WORD) bi. biHeigh t,
(L PSTR) lpB i+ sizeof (B ITMA P IN FOHEADER) + dw SizeCT3 sizeof (RGBQUAD) ,
lpB i,
D IB- RGB- COLORS
)
) ;
: : GlobalU nlock (hData) ;
return hData;
}
213 保存D IB 位图
öö hD ib 为D IB 位图的句柄
ööstrN ame 为保存文件的全路径名
öö全局函数
·88· 物探化探计算技术24 卷
void SaveD ibBmp (HGLOBAL hD ib, CString strN ame)
{
B ITMA PF IL EHEADER bmf; ööD IB 位图文件头
B ITMA P IN FOHEADER bi; ööD IB 位图信息头
L PB ITMA P IN FOHEADER lpB i; ööD IB 位图信息头指针
CF ile file;
CF ileExcep tion fxError;
DWORD dw SizeCT;
lpB i= (L PB ITMA P IN FOHEADER) : : GlobalLock (hD ib) ; öö获得D IB 信息头指针
bi= 3 lpB i;
if (! bi. biSize Image) bi. biSize Image= W IDTHBYTES (bi. biB itCount3 bi. biW idth) 3 bi. biHeigh t;
sw itch (bi. biB itCoun) öö获取每个像素所需要的位数
{
case 1: { dw SizeCT= 2; break; }
case 4: { dw SizeCT= 16; break; }
case 8: { dw SizeCT= 256; break; }
case 24: { dw SizeCT= 0; break; }
default: { dw SizeCT= 0; }
}
öö获得位图文件头的详细信息
bmf. bfType= ′MB′;
bmf. bfSize= sizeof (bmf) + : : GlobalSize (hD ib) ;
bmf. bfOffB its= sizeof (bmf) + bi. biSize+ dw SizeCT3 sizeof (RGBQUAD) ;
bmf. bfReserved1= 0;
bmf. bfReserved2= 0;
öö用CF ile 创建一个二进制文件
if (! file. Open (strN ame, CF ile: :modeCreateûCF ile: :modeW rite, &fxError) )
{
TCHAR buf [255 ];
fxError. GetErrorM essage (buf, 255) ; öö获得出错信息
A fxM essageBox (buf) ; öö显示出错信息
return;
}
öö写入D IB 文件头及文件内容
file. W rite (&bmf, sizeof (B ITMA PF IL EHEADER) ) ;
file. W rite ( (L PSTR) lpB i, bi. biSize+ dw SizeCT3 sizeof (RGBQUAD) + bi. biSize Image) ;
file. Close () ;
öö进行清除
: : GlobalU nlock (hD ib) ;
: : GlobalF ree (hD ib) ;}
3 结束语
作者在本文中解决了VC+ + 程序视图内容导出的问题, 可方便的把视图内容导出成位图。作者在文中
给出了关键代码, 直接把相关代码复制到程序中便可实现位图导出功能。访问链接h ttp: ööw altzforever.
edu. ch inaren. com , 下载Output. zip 文件可得到演示程序与完整演示程序源代码。本文中所使用的方法在
M icrosoft VC+ + 6. 0 平台上运行通过(由VC+ + 6. 0 的AppW izard 生成M FC AppW izard (exe) 工程, 选用
DocumentöV iew 支持, 视图基类选用CScrollV iew 类)。
参考文献:
[ 1 ] David J. Kruglinski. Programm ing V isual C+ + 6. 0 技术内幕(第五版) [M ] . 北京: 北京希望电子出版社, 19991
[ 2 ] 周长发1 精通V isual C+ + 图像编程[M ] . 北京: 电子工业出版社, 20001
[ 3 ] John E. Swanke. VC+ + M FC Extensitons by Examp le[M ] . 北京: 机械工业出版社, 20001
[ 4 ] 刘厉, 周家纪1 位图拼移技术在批量图形处理中的应用[J ] . 物探化探计算技术, 2001, 23 (2) : 1761
[ 5 ] 李火亘, 周家纪1 设备场境化在W indow s GD I 中的应用[J ] . 物探化探计算技术, 1998, 20 (1) : 761
作者简介: 张 弦(1976—) , 男, 中国地质大学(武汉) 地球化学硕士研究生, 研究方向: 计算地球化学, 地
球物质组构的数值图像处理。
1 期朱 剑等: 统一建模语言UML 及应用实例·95·__