Windows通过设备表CDC去创建绘图的环境,通过设备位图DDB和DIB去绘制图形,从内存到窗口,从窗口到内存。
一、什么是位图?
其实就是计算机内存中绘图的最小工具。它分为设备相关位图DDB和设备无关位图DIB。1个1bit位图图像为单显,显示黑or白,8bit位图可以显示2^8=256种颜色。对于1~8bit的位图,需要用调色板来指定位图显示的颜色。
DDB:
设备相关位图。窗口每一位的显示颜色依赖于计算机硬件调色板的位图图像。在256色以下的位图存储的是系统调色板的索引,其颜色依赖于系统调色板。由于DDB高度依赖输出设备,所以DDB只能存在于内存中,视频内存中or系统内存中。
typedef struct tagBITMAP{LONG bmType;LONG bmWidth;LONG bmHeight;LONG WidthBytes;WORD bmPlanes;WORD bmBitPixel;LPVOID bmBits;}BITMAP;
DIB:
设备无关位图。DIB的颜色显示与设备无关,256色以下的DIB拥有自己的颜色表,像素的颜色独立于系统调色板。由于它的不依赖设备性,可以用来永久保存图像。比如BMP图片的保存。
typedef struct tagBITMAPINFO{BITMAPINFOHEADER bmiHeader;RGBQUAD bmiColors[1]; //颜色表 }BITMAPINFO;
二、DDB位图的显示:
1、创建DDB的函数
BOOL LoadBitmap(LPCTSTR lpszResourceName);
BOOL LoadBitmap(UINT nIDResource);
BOOLCreateBitmap(int nWidth,int nHeight,UINT nPlanes,UINT nBitcount,const void * lpBits);
BOOLCreateCompatibleBitmap(CDC * pDC,int nWidth,int nHeight);
int GetBitmap(BITMAP * pBitMap);
typedef struct tagBITMAP{LONG bmType;LONG bmWidth;LONG bmHeight;LONG WidthBytes;WORD bmPlanes;WORD bmBitPixel;LPVOID bmBits;}BITMAP;
2、下面介绍两个与DDB有关的函数。
CDC:BitBlt的声明:BOOL BitBlt(int x,int y,int nWidth,int nHeight,CDC * pSrcDC,int xSrc,int ySrc,DWORD dwRop);
该函数把源设备上下文的位图复制到本身的设备上下文中,pSrcDC指向源设备上下文,xSrc和ySrc说明了原矩形相对于源位图左上角的偏移。参数dwRop指定了光栅操作(ROP)代码。
CDC:StretchBlt的声明:BOOL StretchBlt(int x,int y,int nWidth,int nHeight,CDC * pSrcDC,int xSrc,int ySrc,int nSrcWidth,int nSrcHeight,DWORD dwRop);其中nSrcWidth指定源矩形的宽。
3、DDB的一个重要用途就是用作设备上下文CDC的显示界面。每一个设备上下文都有一个DDB,该位图实际上是在显示设备的缓冲区内,可以将其视为设备上下文的界面,设备上下文用GDI函数绘图其实就是修改它所包含的DDB。内存中的设备上下文可以预先绘制好复杂的图形,然后传递给窗口的设备上下文中,缩短绘图的时间。
三、本例我们通过实例学习MFC绘图的基本原理,下面在窗口左上角绘制一个长方形。
步骤:
1、用VC6.0创建一个单文档MFC程序
2、打开类视图中的CDDBView中的OnDraw函数,编辑如下:
void CDDBView::OnDraw(CDC* pDC)
{
CDDBDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CDC MemDC; //创建一个源设备表对象
CBitmap bm,* oldBmp; //创建甲、乙两个位图类对象,其中后者为指针,它的作用是指向原来的位图区。
MemDC.CreateCompatibleDC(pDC); //创建一个兼容的内存设备上下文,它的作用是为了程序可以去绘图,因为每个设备上下文都包含一个DDB(供绘图用的位图区)
bm.CreateCompatibleBitmap(pDC,100,50); //甲位图对象创建一个与(上句所创建的可兼容的)设备上下文相兼容的DDB(设备相关位图)
oldBmp=MemDC.SelectObject(&bm); //用原位图对象保存刚刚创建的那个DDB位图。因为要供绘图之后还原源设备表
MemDC.SelectStockObject(BLACK_PEN); //设备表使用黑笔
MemDC.SelectStockObject(GRAY_BRUSH); //设备表使用灰刷
MemDC.Rectangle(0,0,50,50); //设备表绘图区域250平方位
pDC->BitBlt(0,0,100,50,&MemDC,0,0,SRCCOPY);//把源设备表的位图区复制到本身的设备上,只有这样程序界面才可接收刚才创建的图
MemDC.SelectObject(oldBmp); //还原源设备表
}
3、编译运行。