VC+ + 视图内容导出成位图的方法

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·__

 

你可能感兴趣的:(C/C++/VC)