DDB(Device-dependent bitmap)
-
DDB
的颜色模式必需与输出设备相一致。例如,如果当前的显示设备是256色模式,那么DDB必然也是256色的,即一个像素用一个字节表示。 -
在256色以下的位图中存储的像素值是系统调色板的索引,其颜色依赖于系统调色板。
由于DDB高度依赖输出设备,所以DDB只能存在于内存中,它要么在视频内存中,要么在系统内存中。 11.3.1 DDB的创建的CBitmap类封装了DDB。该类提供了几个函数用来创建DDB:
BOOL LoadBitmap( LPCTSTR lpszResourceName );
BOOL LoadBitmap( UINT nIDResource );
BOOL CreateBitmap( int nWidth, int nHeight, UINT nPlanes, UINT nBitcount, const void* lpBits );
BOOL CreateCompatibleBitmap( CDC* pDC, int nWidth, int nHeight );
MFC
可以调用CBitmap的成员函数GetBitmap来查询DDB的各种属性(如尺寸):
int GetBitmap( BITMAP* pBitMap );
typedef struct tagBITMAP {
LONG bmType; //
LONG bmWidth; //
LONG bmHeight; //
LONG bmWidthBytes; //
必需为0位图的宽度(以像素为单位)位图的高度(以像素为单位)每一扫描行所需的字节数,应是偶数WORD bmPlanes; //
色平面数WORD bmBitsPixel; //
色平面的颜色位数LPVOID bmBits; //
指向存储像素阵列的数组} BITMAP;
11.3.2 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
构建一个
调用
调用
调用
下面这段代码在视图中显示了一个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,该位图实际上是在显示设备的缓冲区中(如视频内存),我们可以把它看做设备上下文的显示表面,设备上下文用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); //
oldBmp=MemDC.SelectObject(&bm);
MemDC.SelectStockObject(BLACK_PEN);
MemDC.SelectStockObject(GRAY_BRUSH);
MemDC.Rectangle(0,0,50,50); //
创建一个兼容的DDB在DDB中画一个矩形pDC->BitBlt(0,0,100,50,&MemDC,0,0,SRCCOPY);
MemDC.SelectObject(oldBmp); //
使位图bm对象脱离设备上下文. . .
}
在上面的代码中,绘图的结果保存在位图bm中,一旦调用MemDC.SelectObject(oldBmp)使位图bm脱离设备上下文,该位图就可以被其它对象使用。该函数把位图从源矩形拷贝到目的矩形中,如果源和目的矩形尺寸不同,那么将缩放位图的功能以适应目的矩形的大小。函数的大部分参数与
DDB
依赖于具体设备,这主要体现在以下两个方面: