DDB(Device-dependent bitmap)依赖于具体设备,这主要体现在以下两个方面:
由于DDB高度依赖输出设备,所以DDB只能存在于内存中,它要么在视频内存中,要么在系统内存中。
11.3.1
DDB的创建
MFC的CBitmap类封装了DDB。该类提供了几个函数用来创建DDB:
BOOL LoadBitmap( LPCTSTR lpszResourceName );
BOOL LoadBitmap( UINT nIDResource );
该函数从资源中载入一幅位图,若载入成功则返回TRUE。资源位图实际上是一个DIB,该函数在载入时把它转换成了DDB。
BOOL CreateBitmap( int nWidth, int nHeight, UINT
nPlanes, UINT nBitcount, const void* lpBits );
该函数用来创建一幅空白的DDB。参数nWidth和nHeight以像素为单位说明了位图的宽度和高度。nPlanes是DDB的色平面数,nBitcount是每个色平面的颜色位数。一般来说,nPlanes为1,而nBitcount代表DDB中每个像素值所占的位数,但在创建16色DDB时,nPlanes为4,而nBitcount为1。参数lpBits指向存储像素阵列的数组,该数组应该逐行存储位图的每个像素值。注意,数组中每行像素的数目必需是偶数个字节,如果是奇数,则应该用0补足。若创建成功函数返回TRUE。
BOOL CreateCompatibleBitmap( CDC* pDC, int nWidth,
int nHeight );
该函数创建一个与指定设备上下文兼容的DDB。参数pDC指向一个设备上下文,nWidth和nHeight是DDB的尺寸。若创建成功函数返回TRUE。
可以调用CBitmap的成员函数GetBitmap来查询DDB的各种属性(如尺寸):
int GetBitmap( BITMAP* pBitMap );
该函数用来获得与DDB有关的信息,参数pBitMap指向一个BITMAP结构。BITMAP结构的定义为:
typedef struct tagBITMAP {
LONG bmType; //必需为0
LONG bmWidth; //位图的宽度(以像素为单位)
LONG bmHeight; //位图的高度(以像素为单位)
LONG bmWidthBytes; //每一扫描行所需的字节数,应是偶数
WORD bmPlanes; //色平面数
WORD bmBitsPixel; //色平面的颜色位数
LPVOID bmBits; //指向存储像素阵列的数组
} BITMAP;
11.3.2
DDB的用途
DDB的主要用途是保存位图。要保存的位图可以来自资源位图,也可以是一个绘图的结果。
前面说过,在256色以下的显示模式中,DDB中的像素值是系统调色板的索引。一般在系统调色板中除了保留的20种静态颜色外,其它表项都有可能被应用程序改变。如果DDB中有一些像素值是指向20种静态颜色以外的颜色,那么该位图的颜色将是不稳定的。因此,DDB不能用来长期存储色彩丰富的位图。如果位图使用的大部分颜色都是20种保留色,则该位图可以用CBitmap对象保存在内存中。例如,用CDC::LoadBitmap载入的资源位图一般都是颜色较简单的位图,对于那些颜色比较丰富的位图,只有使用下面将要介绍的DIB才能长期保存。
在窗口中显示DDB的方法有些特别,其过程分以下几步:
构建一个CDC对象,然后调用CDC::CreateCompatibleDC创建一个兼容的内存设备上下文。
调用CDC::SelectObject将DDB选入内存设备上下文中。
调用CDC::BitBlt或CDC::StretchBlt将DDB从内存设备上下文中输出到窗口的设备上下文中。
调用CDC::SelectObject把原来的DDB选入到内存设备上下文中并使新DDB脱离出来。
下面这段代码在视图中显示了一个DDB:
void CMyView::OnDraw( CDC* pDC)
{
. . .
CDC MemDC;
CBitmap *oldBmp;
BITMAP bmpInfo;
int bmWidth,bmHeight;
MemDC.CreateCompatibleDC(pDC);
oldBmp=MemDC.SelectObject(&m_Bitmap); //m_Bitmap是一个CBitmap对象
m_Bitmap.GetBitmap(&bmpInfo); //获取位图的尺寸
bmWidth=bmpInfo.bmWidth;
bmHeight=bmpInfo.bmHeight;
pDC->BitBlt(0,0,bmWidth,bmHeight,&MemDC,0,0,SRCCOPY);
MemDC.SelectObject(oldBmp); //使位图m_Bitmap脱离设备上下文
. . .
}
函数CDC::BitBlt的声明为:
BOOL BitBlt( int x, int y, int nWidth, int
nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop );
该函数把源设备上下文中的位图复制到本身的设备上下文中,两个设备上下文可以是内存设备上下文,也可以是同一个设备上下文。参数x和y是目的矩形的逻辑坐标,参数nWidth和nHeight说明了目的矩形及源位图的宽和高。pSrcDC指向源设备上下文,xSrc和ySrc说明了源矩形相对于源位图左上角的偏移。参数dwRop指定了光栅操作(ROP)代码,一些常用的ROP代码如表11.2所示。
表11.2 常用的ROP代码
ROP码
|
含义
|
BLACKNESS
|
输出黑色
|
DSTINVERT
|
反转目的位图
|
MERGECOPY
|
用与操作把图案(Pattern)与源位图融合起来
|
MERGEPAINT
|
用或操作把反转的源位图与目的位图融合起来
|
NOTSRCCOPY
|
把源位图反转然后拷贝到目的地
|
NOTSRCERASE
|
用或操作融合源和目的位图,然后再反转
|
PATCOPY
|
把图案拷贝到目的位图中
|
PATINVERT
|
用异或操作把图案与目的位图相融合
|
PATPAINT
|
用或操作融合图案和反转的源位图,然后用或操作把结果与目的位图融合
|
SRCAND
|
用与操作融合源位图和目的位图
|
SRCCOPY
|
把源位图拷贝到目的位图
|
SRCERASE
|
先反转目的位图,再用与操作将其与源位图融合
|
SRCINVERT
|
用异或操作融合源位图和目的位图
|
SRCPAINT
|
用或操作融合源位图和目的位图
|
WHITENESS
|
输出白色
|
函数CDC::StretchBlt的声明为:
BOOL StretchBlt( int x, int y, int nWidth,
int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth,
int nSrcHeight, DWORD dwRop );
该函数把位图从源矩形拷贝到目的矩形中,如果源和目的矩形尺寸不同,那么将缩放位图的功能以适应目的矩形的大小。函数的大部分参数与BitBlt的相同,但多了两个参数nSrcWidth和nSrcHeight用来指定源矩形的宽和高。
DDB的一个重要用途是用作设备上下文的显示表面。每一个设备上下文都包含有一个DDB,该位图实际上是在显示设备的缓冲区中(如视频内存),我们可以把它看做设备上下文的显示表面,设备上下文用GDI函数绘图实际上就是修改它所包含的DDB(显示表面)的过程。
普通的设备上下文都是在屏幕上绘图的,而使用内存设备上下文则可以在系统内存中绘制图形。内存设备上下文是一种特殊的设备上下文,它将系统内存用作显示表面。程序可以使用内存设备上下文预先在系统内存中绘制复杂的图形,然后再快速地将其复制到实际的设备上下文的显示表面上,而绘制图形的结果仍保存在内存设备上下文的DDB中。
提示:有人可能会想到用BitBlt函数把绘图结果从显示设备拷贝到内存设备上下文中,这种方法可以工作,但有时会出错。当源矩形被别的窗口遮住时,BitBlt会把别的窗口中的像素拷贝下来。 |
内存设备上下文缺省的DDB是一个1×1的单色位图,如此小的显示表面显然是没有用的,因此程序一般要为内存设备对象选择一个合适大小的彩色DDB。
下面这段代码创建了一个内存设备上下文,并在其包含的DDB中画了一个灰色实心矩形,然后再把DDB输出到屏幕上。
void CMyView::OnDraw(CDC* pDC)
{
. . .
CDC MemDC;
CBitmap bm,*oldBmp;
MemDC.CreateCompatibleDC(pDC); //创建一个兼容的内存设备上下文
bm.CreateCompatibleBitmap(pDC,100,50); //创建一个兼容的DDB
oldBmp=MemDC.SelectObject(&bm);
MemDC.SelectStockObject(BLACK_PEN);
MemDC.SelectStockObject(GRAY_BRUSH);
MemDC.Rectangle(0,0,50,50); //在DDB中画一个矩形
pDC->BitBlt(0,0,100,50,&MemDC,0,0,SRCCOPY);
MemDC.SelectObject(oldBmp); //使位图bm对象脱离设备上下文
. . .
}
在上面的代码中,绘图的结果保存在位图bm中,一旦调用MemDC.SelectObject(oldBmp)使位图bm脱离设备上下文,该位图就可以被其它对象使用。
追寻梦想首页 编程乐园首页
本教程幼髡? 作者: 不详, 来源: Visual C++王朝