位图即后缀为bmp的图形文件,MFC中有专门的函数处理这种格式的图形文件。这些函数只能处理作为MFC资源的bmp图,没有操作文件的功能,受限较多,一般常作为程序窗口界面图片、显示背景图片等用途。有关位图操作的步骤、相关函数等介绍如下。
一、将bmp文件导入VS成为MFC中的资源
步骤:解决方案资源管理器->右键资源文件->添加->资源->Bitmap->导入。
此时,bmp文件已经进入到MFC中成为MFC的资源;在资源视图中,点开Bitmap,可以看到“IDB_BITMAP1”,这就是导入位图的ID号,右键这个ID号可通过属性修改ID号。在后面的处理过程中,需要使用这个位图时,都要提供这个ID号。
二、位图操作函数
(一)创建与指定设备上下文兼容的内存设备上下文函数
原型:virtual BOOL CreateCompatibleDC(CDC* pDC)
参数:pDC是显示设备上下文的指针
返回:创建成功返回非0数(真);否则返回0(假)
说明:
a.这个函数是CDC类的成员函数,使用这个函数时需要CDC类对象或指针调用。
b.所谓设备上下文就是计算机的显示设备,具体到我们这里就是显示窗口。函数的参数即是当前显示窗口的指针,这里利用这个指针并调用CreateCompatibleDC函数的目的就是生成一个与当前显示窗口相兼容的CDC类对象(在内存中),然后在这个对象中处理bmp位图资源。由于彼此兼容,可以将处理好的兼容对象中的内容一次性传送到当前显示窗口中。
(二)载入位图函数
原型:BOOL LoadBitmap(UNIT nIDResource);
参数:nIDResource位图资源ID编号
返回值:载入成功返回非0值,失败返回0
说明:
a.函数LoadBitmap属于CBitmap类的成员函数,使用这个函数需要CBitmap对象调用。
b.参数就是前面介绍的导入到MFC中的bmp资源的ID。
c.通过这个函数,位图资源从MFC系统资源被导入到我们的程序中,我们可以对其操作了。
(三)获取位图信息函数
原型:int GetBitmap(BITMAP* pBitMap);
参数:pBitMap是BITMAP结构体的指针
返回值:获取信息成功返回非0数;失败返回0。
说明:
a.函数GetBitmap是CBitmap类的成员函数,使用时需要CBitmap类对象调用。
b.实际上获取的信息就是调用它CBitmap对象的信息,包括位图的宽度、高度、颜色格式和位图的字节数据等信息。
c.从步骤上说,CBitmap对象应先通过调用LoadBitmap函数载入位图。
(四)位块传送函数
原型:BOOL BitBlt(int x,int y,int nWidth,int nHeight,CDC* pSrcDC,int xSrc,int ySrc,DWORD dwRop);
参数:x,y,nWidth、nHeight目标矩形左上角坐标和源位图的宽高
pSrcDC是CDC对象的指针,指向被拷贝的位图
xSrc和ySrc是源位图的左上角
dwRop光栅操作码
返回值:传送成功返回非0数;失败返回0。
说明:
a.函数BitBlt是CDC类的成员函数,使用时需要CDC类对象、指针调用。
b.该函数的功能是将源位图中部分或全部区域按原区域大小复制到目标对象。
c.当目标矩形指针指向当前窗口时,被拷贝的内容会显示到屏幕上。
d.关于光栅操作码的取值有很多,如仅仅是把位图显示到窗口,取值为SRCCOPY。如需要对图像像素进行处理可以选用其它光栅操作码。
(五)拉伸位图函数
原型:BOOL StretchBlt(int x,int y,int nWidth,int nHeight,CDC* pSrcDC,int xSrc,int ySrc,int nSrcWidth,int nSrcHeight,DWORD dwRop);
参数:x,y,nWidth,nHeight目标矩形坐标及长宽
pSrcDC是CDC类对象指针,指向源位图
xSrc、ySrc,nSrcWidth、nSrcHeight源位图矩形坐标及长宽
dwRop 光栅操作码
返回值:处理成功返回非0数,否则返回0。
说明:
a.函数StretchBlt是CDC类的成员函数,使用时需要CDC类指针调用。
b.该函数的功能不仅仅是字面含义的拉伸,也可以压缩、变形等。
c.当目标矩形指针指向当前窗口时,被拷贝的内容会显示到屏幕上。
d.光栅操作码同上一个函数。
e.当目标矩形长宽与源矩形长宽一致时,函数的功能与BitBlt相同。
f.由于这个函数在处理过程中存在变形,会造成图像显示失真,为解决失真问题,可以在调用StretchBlt函数前,调用SetStretchBltMode函数设置一下拉伸模式,参数使用COLORONCOLOR或HALFTONE就不变形了。SetStretchBltMode函数是CDC类的成员函数,使用时需要CDC对象或指针调用。
e.关于坐标系问题,建议使用设备坐标系;上面那个函数也同样。
三、MFC中关于位图的操作函数,既复杂功能又弱,使用起来效果不是太好,关于图像处理,有一个共享类CImage,它可以在C++、MFC中调用,笔者曾写过一篇短文《CImage成员函数Load、Create、Draw、Save使用方法简介》介绍了它的主要函数以及在C++中的使用,在笔者“C++/MFC/easyX相关知识”专栏中可以看到,这个类功能强大,使用简单。方便时将对这个类更多的函数以及在MFC中的使用做进一步的介绍。
四、上面几个函数的使用方法的举例程序
题目:将一张荷花图片显示到窗口上,然后画一个红色边框填充为透明的椭圆,将图片中的荷花圈起来。步骤如下:
(一) 先按照本文开头讲的步骤,将bmp图形文件导入到MFC中,ID号使用缺省ID:IDB_BITMAP1。
(二)其它代码及注释如下:(运行时将代码考入OnDraw函数中)
//一、获得窗口数据
CRect rect;
GetClientRect(rect);
//使用设备坐标系,这里获取窗口数据是为了后边显示图片使用
//二、载入一幅荷花图片并显示在窗口
CDC myDC; //声明CDC对象
myDC.CreateCompatibleDC(pDC); //初始化myDC是指与pDC兼容
CBitmap myBitmap;//声明位图类对象
myBitmap.LoadBitmapW(IDB_BITMAP1);//将MFC位图资源载入位图对象
CBitmap* oldBitmap = myDC.SelectObject(&myBitmap); //将位图对象选入兼容CDC类对象
BITMAP info; //声明位图结构体对象
myBitmap.GetBitmap(&info);//获取位图长宽等信息
pDC->SetStretchBltMode(COLORONCOLOR);//设置拉伸位图模式
pDC->StretchBlt(0, 0, rect.Width(), rect.Height(), &myDC, 0, 0, info.bmWidth,info.bmHeight,SRCCOPY);
//使用拉伸位图函数将位图(来自于MFC资源)传送到屏幕上的窗口中
pDC->SelectObject(oldBitmap);//恢复CDC中的缺省位图
myBitmap.DeleteObject();//清空bitmap对象
myDC.DeleteDC();//清空memDC
//三、画一个边框红色、填充为透明的圆
CPen redPen(PS_SOLID,3,0x0000ff);//声明红色画笔
CPen* oldPen=pDC->SelectObject(&redPen); //将画笔选入CDC
CBrush* oldBrush =(CBrush*)pDC->SelectStockObject(NULL_BRUSH);//选入透明库画刷
pDC->Ellipse(300, 100, 900, 500);//画椭圆
pDC->SelectObject(oldPen);//恢复缺省画笔
pDC->SelectObject(oldBrush);//恢复缺省画刷
运行结果截图: