⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 10.7 位图的显示.txt

📁 网上第一本以TXT格式的VC++深入详解孙鑫的书.全文全以TXT格式,并每一章节都分了目录,清晰易读
💻 TXT
字号:
10.7 位图的显示
有多种方法可以实现在窗口中显示位图,如图 10.39所示的步骤是其中的一种 :
1.创建位图 	2.创建兼容 DC 
CDC dcCompatible; 
Cbitmap bitmap; 

dcCompatible.CreateCompatibleDC(pDC)
bitmap.LoadBitmap(IDB_BITMAPI); 
4.将兼容 DC中的位图贴到当前 DC中 
3.将位图选入兼容 DC中 
dcCompatible.SelectObject( &bitmap); 	Pdc->Bi tB lt(rec t. le仇, r田t.top, rec t.Wid
由(),) rect. Height( ),&dcCompatible, 0, 0, SRCCOPY); 

兼容 DC
4 	
当前 DC
位因 
图 10.39显示位图的步骤

如图 10. 39所示的这种方法的第一步是创建位图,这可以先利用 CBitmap构造一个位图对象,然后
利用 LoadB itmap函数加载一幅位图资源。
第二步是创建兼容 DC。其中 CreateCompatibleDC函数将创建一个内存设备上下文,与参数 pDC所
指定的 DC相兼容。内存设备上下文实际上是一个内存块,表示一个显示的表面。如果想把图像复制
到实际的 DC中,可以先用其兼容的内存设备上下文在内存中准备这些图像,然后再将这些数据复制
到实际 DC中。
第三步是将位图选入兼容 DC中。当兼容的内存设备上下文被创建时,它的显示表面是标准的一个单
色像素宽和一个单色像素高。在应用程序中可以使用内存设备上下文进行绘图操作之前,必须将一
个具有正确高度和宽度的位图选入设备上下文,这时,内存设备上下文的显示表面大小就由当前选
入的位图决定了。
第四步是将兼容 DC中的位图贴到当前 DC中。有多个函数可以以几种不同的方式完成这一操作。如
图 10.39所示的例子是调用 BitBlt函数将兼容 DC中的位图复制到当前 DC中。该函数的声明形式如
下所示: 
BOOL BitBlt(int x , int y , int nWidth , int nHeight , CDC* pSrcDC , int xSrc , 工 nt ySrc , 
DWORD dwRop ) ; 
BitBlt函数的功能是把源设备上下文中的位图复制到目标设备上下文中。该函数带有 8个参数,各
参数含义如下所述: 
. x和 y
指定目标矩形区域左上角的 x和 y坐标。 

. 
. nWidth和 nHeigh t
指定源和目标矩形区域的逻辑宽度和高度。因为该函数在复制时是按照 1 : 1的比例进行的,所以
源矩形区域和目标矩形区域的宽度和高度是相同的。
. 
"‘ I 399 

. pSrcDC 
指向源设备上下文对象。 
. xSrc和ySrc
指定源矩形区域左上角的x和y坐标。 

. dwRop 
指定复制的模式,也就是指定源矩形区域的颜色数据,如何与目标矩形区域的颜色数据组合以得到
最后的颜色。表10.5列出了常见的复制模式。
表10.5复和l模式

模式 说明 
BLACKNESS  表示使用与物理调色板中索引0相关的色彩来填充目标矩形区域(对默认的物理调用扳
而言,该 颜色为黑色)  
DSTINVERT  表示使目标矩形区域颜色取反 
如但RGECOPY 表示使用与操作将源矩形区域的颜色与特定模式相组合  
MERGEPAINT  通过使用或操作将反向的源矩形区域的颜色与目标矩形区域的颜色合并  
NOTSRCCOPY  将源矩形区域的颜色取反,再复制到目标矩形区域  
NOTSRCERASE  使用或操作组合源和目标矩形区域的颜色值,然后将合成的颜色取反  
PATCoPY  将特定的模式复制到目标位图上 
PA:τ1NVERT  使用或操作将源矩形区域取反后的颜色值与特定模式的颜色合并,然后使用或操作
将该操作的结 果与目标矩形区域内的颜色合并  
PAll吁TINVERT 通过使用异或操作将目标矩形区域内的颜色与特定模式的颜色合并  
SRCAND  通过使用与操作将源和目标矩形区域内的颜色合并  
SRCCOPY  将源矩形区域直接复制到目标矩形区域  
SRCERASE  通过使用与操作将目标矩形区域颜色取反后与源矩形区域的颜色值合并  
SRCINVERT  通过使用异或操作将源和目标矩形区域的颜色合并  
SRCPAll吁T 通过使用或操作将源和目标矩形区域的颜色合并 
WHlTENESS  使用与物理调色板中索引 1相关的色彩来填充目标矩形区域(对默认的物理调用板而
言,该颜色 为白色) 

如果函数调用成功,则BitBlt函数将返回非O值:否则返回0。下面,我们就可以按照上述四个步骤,
来完成在窗口显示位图的功能。首先需要准备一幅位图。本例使用的位图是通过把整个桌面抓取下
来并保存而得到
的,该位图文件位于随书附带光盘上本章示例程序的res目录下,文件名为background.bmp

0 
读者可以使用自己喜爱的任一幅位图。然后在Graphic工程中,选择【Insert\Resource..】菜单项,
在打开的Insert Resource 对话框上选择Bitmap资源类型,如图 10.40所示。
然后单击【Import】按钮,弹出Import Resource对话框。在此对话框上,将文件类型选择为"所有
文件 C*.*)",然后通过该对话框上提供的浏览按钮找到要插入的位图所在目录,并选中该文件,如
图 10.41所示。
单击【Import】按钮,系统将弹出一个提示信息框(如图 10.42所示),提示:位图己成功插入工程,
但因其包含的颜色超过了256种,故不能在位图编辑器中被加载。

it川、 .ttkI'M.Utu~ 	J-


.1.I.!!l |Import Re四川四	川制'四-W29 
酣范,ω; r宫rn 	3 *'巴d国·

Rc.,回国民范伽细回:
旦J

,怜 Acct:lcr咽。,
国lidll.@ii 
. ~ Cursor 旦~g回国
Olalog 旦巳」
HTTr.4 l 
1四n 
旦旦J 
Tr.4 enu 
赢画 Strlng Table 
是, τoolbar 


. Verslon 	立件4ω Ibackcround.. b.p 33单半j 
M蛐ω-际在需ττ:IIUI! I 

Open "8: IAuto 

图 10.40插入位图资源	图 10.4 1从位图文件中导入位图资源
|叫IIIIt1."nJ川sual ( + + 	-_:ft,;,;-(祸圃'主J 
& 忏回城"咽h田beenInport国correctly,hc响帽,bec剧曾在阳忧西1$more th耐Z臼呻::wsltc回回
国Ioeded怕阳峙m崎od段时.


图 10.42提示信息对话框

国	际: VC叫我们提供的位图编辑器只能编辑256色或更少颜色的位图,
超过256色的位图就不能被加载了,但这幅位图在程序中是能正常使用的。

接下来完成位图的显示。首先我们需要了解一下窗口的绘制过程,包含两个步骤:首先擦除窗口背景,
然后在对窗口重新进行绘制。
当擦除窗口背景时,程序会发送一个 WM_ERASEBKGND消息,因此可以在此响应函数中完成位图的显
示。另外,根据前面的知识,可以知道应该在视类窗口中进行位图的绘制。因此为Graphic工程的 
CGraphicView类添加WM_ERASEBKGND消息的响应处理函数: OnEraseBkgnd。然后按照前面介绍的步
骤,在此函数中实现位图的显示。结果代码如例 10-34所示。
例10-34 

1 . BOOL CGraphicView: : OnEraseBkgnd(CDC* pDC) 
2. { 
3 . // TODO : Add your message 	handler code here and/ or call default 


4 . 	CBitmap bitmap; 


5. 	bitmap . LoadBitmap(工DB_BITMAP1) ; 
6. 	CDC dcCompatible ; 
7 . 	dcCompatible . CreateCompatibleDC(pDC) ; 
8. 	dcCompatible . SelectObject(&bitmap) ; 

9. 	CRect rect; 

10. GetClientRect (&rect) ; 

11. pDC->BitBlt(O , O, rect . Width() , rect .Height() , &dcCompatible , O, O, SRCC OPY) ; 



‘~..‘ I 401 
第10 
. 
12 . return C飞liew : :OnEraseBkgnd(pDC} ; 

13. } 


在上述如例 10啕34所示的代码中,首先构建位图对象:bitrnap,并加载位图: IDB_BITMAP1,接下
来创建与当前DC (pDC)兼容的DC: dcCompatible。第三步,调用 SelectObject函数将位图选入兼容
DC中,从而确定兼容DC显示表面的大小。第四步,将兼容DC (dcCompatible)中的位图复制到目的DC 
(pDC)中,因为要指定复制目的矩形区域的宽度和高度,这时首先需要得到目的DC客户区大小,所以
就构造一个CRect对象,然后调用GetC1ientRect函数得到客户区大小。接下来就可以调用BitB1t函
数复制了,这里,源DC就是先前创建的兼容DC,复制模式选择: SRCCOPY,就是将源位图复制到目的
矩形区域中。最后,调用视类的基类 (即CView)的OnEraseBkgnd函数。 
Bui1d并运行Graphic程序,但是看到程序窗口在显示时,位图只是闪了一下就消失了。这主要是因
为在上述OnEraseBkgnd代码中,在调用 BitB1t函数复制位图之后,又调用了视类的基类(即 CView)
的OnEraseBkgnd函数,该函数的调用把窗口的背景擦除了,所以就出现了我们看到的效果,位图只
是闪了一个就消失了。
对OnEraseBkgnd函数来说,如果其擦除了窗口背景,将返回非O值。因此上述例 10-34所示
CGraphicView类的OnEraseBkgnd函数的最后,不应该再调用其基类的 OnEraseBkgnd函数,而是应该
直接返回TRUE值,即把上述如例 10-34所示OnEraseBkgnd函数中第 12行代码替换为下面这行代码: 
return TRUE; 
再次运行Graphic程序,在程序窗口中就可以看到我们显示的位图了,如图 10.43所示。
|.二龙酝蛊 Gt呻lllIε恶r. .101足j

图 10.43利用BitBlt实现在窗口中显示位图

读者可能注意到了:位图在窗口中并没有完整地显示出来。如果窗口放大些,就可以看到更多的位图
部分。有时我们需要在窗口中完整地显示一幅位图,如果位图比窗口大,
就要压缩位图:如果小,就要拉伸位图。然而BittBlt函数是没有办法实现压缩和拉伸的,因为它是
按照 1:1的比例进行复制的,所以这里再介绍另一个函数显示位图的函数: S位etchBlt,其声明形
式如下所示: 
BOOL StretchBlt (int x , int y , int nWidth, int nHeight , CDC* pSrcDC , int xSrc , int 
ySrc , int nSrcwidth, int nSrcHeight , DWORD dwRop ); 
该函数与前面介绍的BitBlt函数的功能基本相同,都是从源矩形区域中复制一个位图
402 I胁" 
vc忡深λ详解

到目标矩形,但是与 BitB lt函数不同的是, StretchBlt函数可以实现位图的拉伸或压缩,以适合
目的矩形区域的尺寸。
与 Bi由lt函数相比, StretchBlt函数只是多了两个参数 : nSrcWidth和 nSrcHeight,分别用来指
示源矩形区域的宽度和高度。
前面已经说过了,兼容 DC原始只有 1个像素大小。它的大小由选入的位图的大小所决定,也就是说,
如果想要得到源矩形的宽度和高度,就要想办法得到选入的位图的宽度和高度。后者可以通过调用 
CBitmap类的 GetBitmap函数来得到,该函数的原型声明如下 : 
int GetBitmap( BITMAP* pBitMap ); 
该函数有一个参数,是一个指向 BITMAP结构体的指针,该函数将用位图的信息填充这个结构体。 
BITMAP结构体的定义如下所示: 
typedef struct tagBITMAP { 1* bm *1 

工 nt bmType; 
int bmWidth ; 
int bmHeight ; 
int bmW工 dthBytes ; 
BYTE bmPlanes; 
BYTE bmBitsPixel ; 
LPVO工 o brnB its; } BITMAP; 
其中 bmWidth指示位图的宽度, bmHeight指示位图的高度。因此在上述例 10-34所示 CGraphic 
View类的 OnEraseBkgnd函数中,在位图对象 bitmap成功加载位图资源(即第 5行代码)之后,添加
下述代码: 
B工 TMAP bmp; 
bitmap.GetBitmap(&bmp) ; 
接下来就可以调用 StretchBlt函数复制位图了。首先将上述例 10-34所示 CGraphic View 类的 
OnEraseBkgnd函数中调用 Bi tB lt函数的语句注释起来,然后在其后添加下面的语句: 
pDC->StretchBlt(O , O, rect.Width() , rect.Height() , &dcCompatible , O, O, bmp.bm Width, 
bmp.bmHeight , SRCCOPY); 
Bu i1d井运行Graphic程序,这时就可以看到整幅位图都显示出来了,如图 10.44所示。 

. 
图 10.44利用 StretchB lt实现在窗口中显示位阁
喝喝.....‘ 1403 


本例是在窗口显示更新的第一步,即擦除窗口背景这一步实现位图的显示,读者在实现时,也可以
在窗口显示更新的第二步,即重绘窗口时实现这一功能。我们知道窗口重绘时会调用 OnDraw函数,
因此可以把上述显示位图的代码放到这个函数中,读者可以自行试验这种方法,将会看到程序显示
的结果是-样的,但是这种方式产生的效果是不一样的,当窗口尺寸发生变化时,程序窗口会有闪烁
现象,这是因为当窗口尺寸发生变化时,会引起窗口重绘操作,它会首先擦除背景,然后在 OnDraw
函数中再重新贴上位图。而前一种实现方式下,窗口闪烁比较小。因为我们没有擦除背景,而是直
接贴上位圈。当然这里还可以做一些改进,读者可以自己实践一下。由此可见,在窗口中显示-幅位
图时,除了需要将其正确地显示出来以外,同时还应注意显示效果。如果我们非常清楚窗口重绘的
原理,就可以知道在哪个过程中完成图形的显示比较合理。

飞结

本章主要介绍了图形绘制时的一些控制,包括 z
·
设置对话框、颜色对话框、字体对话框的创建,并根据用户的设置控制图形的绘制 1


·
在对话框上增加示例功能:

·
改变对话框及其上控件的背景色和文本颜色,以及字体:

·
在窗口中显示位图。


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -