创建步骤
我们首先大致了解下显示位图的基本步骤,主要有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函数由于有压缩或者拉伸造成图片失真。