创建步骤
我们首先大致了解下显示位图的基本步骤,主要有5步,如图1所示:
图1 位图显示步骤
对每个过程的解释如下:
1.创建位图
利用CBitmap类构造一个位图对象,然后利用LoadBitmap函数完成实际位图资源和对象的关联.
2.创建兼容DC
在OnDraw或OnEraseBkgnd函数的入参是CDC对象指针,指示了当前实际显示设备的相关信息;我们利用CreateCompatible函数创建一个内存设备上下文,和参数pDC所指定的DC相兼容。内存设备上下文实际上是一个内存块,表示一个显示的表面,可以认为是虚拟的设备显示环境。
3.将位图选人兼容DC中
当兼容的内存设备上下文被创建时,它的表面是标准的一个单色像素宽和一个单色像素高,我们需要将具有有正确的宽度和高度的位图选人兼容DC,才能正确的显示。
4.将兼容DC中的位图粘贴到当前DC
我们可以利用BitBlt函数或者StrechBlt函数完成兼容DC中的图像到实际DC的搬移和显示。
5.位图显示
利用窗口绘制过程的两个时机完成位图显示,一个窗口绘制过程包括两个步骤:首先是利用画刷擦除窗口背景,其次是再对窗口重新进行重绘;擦除是调用OnEraseBkgnd函数,重绘是调用OnDraw函数。
函数说明
BitBlt函数是以1:1的比例完成拷贝,而StrechBlt函数则可以进行图片的压缩或者扩展,它们的函数声明和参数函数如下所示,更加具体的信息参数MSDN:
BitBlt函数声明如下:
BOOL BitBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop ); 返回值:函数成功,返回非零值,否则为0。 参数: x 指定目标矩形左上角的逻辑x坐标。 y 指定目标矩形左上角的逻辑y坐标。 nWidth 指定目标矩形和源位图的宽度(逻辑单位)。 nHeight 指定目标矩形和源位图的高度(逻辑单位)。 pSrcDC 指向CDC对象的指针,标识待拷贝位图的设备上下文。 xSrc 指定源位图左上角的逻辑X坐标。 ySrc 指定源位图左上角的逻辑Y坐标。 dwRop 指定要执行的光栅操作
StrechBlt函数声明如下:
BOOL StretchBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, intxSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop ) 返回值:如果位图已经绘制,则返回非零值,否则为0。 参数: x 目标矩形左上角的X逻辑坐标。 y 目标矩形左上角的Y逻辑坐标。 nWidth 目标矩形的宽度(逻辑单位)。 nHeight 目标矩形的高度(逻辑单位)。 pSrcDC 指定源设备上下文。 xSrc 源矩形左上角的X逻辑坐标。 ySrc 源矩形左上角的Y逻辑坐标。 nSrcWidth 源矩形的宽度(逻辑单位)。 nSrcHeight 源矩形的高度(逻辑单位)。 dwRop 指定光栅操作。
功能代码
我们这里以OnEraseBKgnd消息响应函数完成整个显示功能,该函数在视类中进行响应,具体代码如下:
BOOL CCBmpViewView::OnEraseBkgnd(CDC* pDC) { // TODO: 在此添加消息处理程序代码和/或调用默认值 //创建位图对象 CBitmap bitmap; bitmap.LoadBitmap(IDB_BITMAP1); //获取位图信息 BITMAP bmp; bitmap.GetBitmap(&bmp); //创建兼容DC CDC dcCompatible; dcCompatible.CreateCompatibleDC(pDC); //将位图选入兼容DC dcCompatible.SelectObject(&bitmap); //向实际DC输出图片 CRect rect; GetClientRect(&rect); //1比1格式输出图片 //pDC->BitBlt(0,0,rect.Width(), rect.Height(),&dcCompatible,0,0,SRCCOPY); //适应实际窗口大小进行图片压缩或者拉伸输出 pDC->StretchBlt(0,0,rect.Width(), rect.Height(),&dcCompatible,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY); return TRUE; }运行效果:
效果分析
通过两种方式进行对比发现,若我们的位图大小比窗口小,以OnEraseBkgnd函数和BitBlt函数进行输出图片,改变窗口大小会有窗口的残留痕迹;若以OnDraw函数和BitBlt函数进行输出则没有这样的问题,但是会带来视觉上的闪烁;StrechBlt函数由于有压缩或者拉伸造成图片失真。