|
* s* Y3 m3 T+ c4 s7 U" V
西安交通大学流体机械研究所 . e! {' J9 \: V" N. f: i
张义云
4 V9 q8 ?( @1 u
4 R+ r. O9 }/ ?! [, A1 x2 O$ w" t---- 用普通方法显示BMP位图,占内存大,速度慢,在图形缩小时,失真严重, 9 T: c: w" b) Q+ U# p
在低颜色位数的设备上显示高颜色位数的图形图形时失真大。本文采用视频函数
/ b0 c4 Y- ~' n显示BMP位图,可以消除以上的缺点。 ! q6 f" k* f0 g. w( k }
* l* B+ H+ N, b5 G# y" o6 N
---- 一、BMP文件结构
& t" A: g5 I0 ~% Y9 U2 m, E
& c+ Y# B! O" a( _---- 1. BMP文件组成
( L# w/ U3 b3 C
/ H$ g4 p* @5 a* K4 ]: X---- BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。 " E3 M. p3 R# h5 F. G) c
! o- f* k/ h. l" @& i0 J
---- 2. BMP文件头 3 O2 B" @, K, ~3 k* `
+ s' j1 @' i8 i6 S; l
---- BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息 & K# L+ ?9 J9 g- J
。
! E( W8 ? J2 q. q/ A * x, q9 i3 Y: |. N8 O( r
---- 其结构定义如下:
6 A$ l7 l8 Y; G/ B" Q! v
- E9 m8 O, P; N2 V7 L3 B- v8 g- Ztypedef struct tagBITMAPFILEHEADER
" P3 {1 u9 Q5 n; A* `' c9 s W{
; {. w) s* a1 Z: A2 q# \ iWORDbfType; // 位图文件的类型,必须为BM
' H+ G9 W1 x6 S+ b6 u) a" eDWORD bfSize; // 位图文件的大小,以字节为单位 7 b, Y7 p: B5 w7 D6 m6 ^
WORDbfReserved1; // 位图文件保留字,必须为0 * u( @! h3 L! H" j$ s6 m) M1 y: {
WORDbfReserved2; // 位图文件保留字,必须为0 " B, p3 w* M% d1 t$ {2 z2 ~. @
DWORD bfOffBits; // 位图数据的起始位置,以相对于位图
+ M" J% w, U+ ]7 l; x/ Z: c// 文件头的偏移量表示,以字节为单位 4 [* `2 u! J4 w+ K$ y: }
} BITMAPFILEHEADER;
* ]' r8 \0 d1 _7 \3 i; X2 j ' j7 D, s4 \/ k9 H' }! z
/ S+ A$ U9 \7 J---- 3. 位图信息头 9 V. a; z7 m+ B* |
---- 4 }& `2 D/ c7 p4 N& @& `- \; ]' ~
7 J/ y0 _/ z7 E/ s, C( w( A' YBMP位图信息头数据用于说明位图的尺寸等信息。 6 u3 s" H/ j4 d, V
typedef struct tagBITMAPINFOHEADER{
' q7 J9 q, k+ c" K. r* ]& i DWORD biSize; // 本结构所占用字节数
! n$ x9 i" r9 n6 v2 ^ LONGbiWidth; // 位图的宽度,以像素为单位 4 T9 _- P6 t4 W% }$ F G
LONGbiHeight; // 位图的高度,以像素为单位 ( M5 y [8 O% z7 Q3 V+ g1 v
WORD biPlanes; // 目标设备的级别,必须为1
! v0 m7 R8 y9 x' v+ D S+ y& E WORD biBitCount// 每个像素所需的位数,必须是1(双色),
, Y. ^2 _% B" B2 z: D6 [ // 4(16色),8(256色)或24(真彩色)之一
; i4 h1 X$ P8 N1 ~ DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),
6 {+ Y! P- o! X, f8 W( @$ b // 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一 - r) j' `1 `% o1 T: X+ D
DWORD biSizeImage; // 位图的大小,以字节为单位 ( E: g5 [& X* h! [" `
LONGbiXPelsPerMeter; // 位图水平分辨率,每米像素数 # p! _) v5 T+ J- [8 o4 ~: @3 V* [
LONGbiYPelsPerMeter; // 位图垂直分辨率,每米像素数
0 }3 W% Z/ H6 t9 w1 S2 e |& H DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数 9 r2 Y5 }( U& M3 N5 {6 i0 K' H
DWORD biClrImportant;// 位图显示过程中重要的颜色数 0 m* B" @5 _% j0 R5 |4 @) j
} BITMAPINFOHEADER; ! N5 E7 S& T9 u* o4 p
^ H7 |; l; N8 \1 K1 N" e
M8 X! w2 A! f l+ K% s9 d" K0 @( N---- 4. 颜色表 1 Q k1 {' O3 a; A4 n5 J! B. O
---- 颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个 4 g! [! a2 U+ h( x
RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下: k, C; n6 W# z0 G
' Q( F% _( E/ D2 o: ?! d0 [' Ftypedef struct tagRGBQUAD { ' f W5 c$ \5 e9 t2 _8 W; m9 o
BYTErgbBlue;// 蓝色的亮度(值范围为0-255) / P) i( ]8 q. {4 u4 |
BYTErgbGreen; // 绿色的亮度(值范围为0-255) " t7 b# }2 e! n% h) S3 y! ~
BYTErgbRed; // 红色的亮度(值范围为0-255) 7 c! H* D j M, M1 i, W
BYTErgbReserved;// 保留,必须为0 3 n* ]+ ]. A6 w
} RGBQUAD;
4 c9 R7 l3 N5 ~7 z颜色表中RGBQUAD结构数据的个数有biBitCount来确定: ( ?7 ?& y- D. |# i" x0 ~6 a0 }
当biBitCount=1,4,8时,分别有2,16,256个表项;
# U( _4 o: i4 O/ d3 O当biBitCount=24时,没有颜色表项。
4 d- z0 g9 {' | 位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下: & C8 x1 x2 ^: K6 _$ o- ^% p1 n
typedef struct tagBITMAPINFO {
% u% T1 s" u: v1 ]7 K1 d% V# P6 Q2 M+ R BITMAPINFOHEADER bmiHeader; // 位图信息头
3 f1 X: _# K. v RGBQUAD bmiColors[1]; // 颜色表 $ M8 D$ P! H/ ^* {5 Q
} BITMAPINFO;
, H' ~9 s3 E3 J% i: K) j2 |* A
$ {! d% I" y/ O. J & u$ h# G) X6 j8 z8 k( z
" D& a$ z7 A( z# k- A3 H' N; }
---- 5. 位图数据
, H0 ^9 U! A# w/ T4 M---- 位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右 ( @+ o4 n" y- N0 {& H0 r6 [( ]3 `) C
,扫描行之间是从下到上。位图的一个像素值所占的字节数:
|( q% w& o% M4 U" F, s- r3 g2 T % v- }7 f! H- |. V; N7 g, v. x
当biBitCount=1时,8个像素占1个字节; : h7 G7 t8 M+ F* ]% F9 L
当biBitCount=4时,2个像素占1个字节; # Z0 d. @5 w& F/ S. G( @
当biBitCount=8时,1个像素占1个字节;
5 [: p7 u' A- M/ E当biBitCount=24时,1个像素占3个字节;
. A& b, N% G/ nWindows规定一个扫描行所占的字节数必须是 1 Z1 _ G; e5 x4 c
4的倍数(即以long为单位),不足的以0填充,
3 X5 w7 c9 A% m+ x一个扫描行所占的字节数计算方法:
: A! G$ A6 K- D5 @( tDataSizePerLine= (biWidth* biBitCount+31)/8; & ` p9 V" g+ C( J
// 一个扫描行所占的字节数
- A. M' k$ D1 p% u) W% b4 EDataSizePerLine= DataSizePerLine/4*4; // 字节数必须是4的倍数
1 K0 p5 L2 Q/ l' E' W2 D4 D! W; Q位图数据的大小(不压缩情况下): 7 h6 G. H/ j# N
DataSize= DataSizePerLine* biHeight; v8 ?9 l. ?$ l) Q) K1 ~" c$ U
, T; }" R6 B$ }4 A" Q9 v T
0 R' ^0 u8 {7 h% y* ]---- 二、BMP位图一般显示方法 . J& ?2 u* [+ H- t2 m7 _
---- 1. 申请内存空间用于存放位图文件 : P6 {2 e2 \/ ^
3 t% i. ~/ u* L( D9 J7 C9 d1 f& o5 C! ^& L+ B---- GlobalAlloc(GHND,FileLength);
3 y3 `% l, {# x) r, l; C % R( {$ ~6 E: l
---- 2. 位图文件读入所申请内存空间中
8 s, s6 T1 o8 D2 M3 k" l
6 q& Y! D5 Q2 b0 }$ ?" ?. U. V---- LoadFileToMemory( mpBitsSrc,mFileName);
- B7 e+ m& `% j U! ~. Z& U
/ w) U" w+ {4 h1 |1 |7 P/ {: e---- 3. 在OnPaint等函数中用创建显示用位图
- q/ ?1 w, t l5 ?. I' K5 N ) z* d! f8 P' Q& i G9 E2 f/ M6 G
---- 用CreateDIBitmap()创建显示用位图,用CreateCompatibleDC()创建兼容
7 V6 Y" k: z7 {% h% tDC, 8 P& G+ ^/ g* a' c
. f( A. V; z9 a2 i: \7 `7 t; y---- 用SelectBitmap()选择显示位图。
5 Y( w4 L% c6 X; y6 I% D & t4 z$ P0 b" n" c8 q3 d# `( z
---- 4. 用BitBlt或StretchBlt等函数显示位图
7 }& x: H) f7 ~7 j3 p1 j
* } [- `7 Z% D4 w' }0 h5 x: v4 H/ `---- 5. 用DeleteObject()删除所创建的位图 ) }. v: {8 V; j' k' [/ E
2 p1 ~/ Q: I; Y6 a/ }0 B---- 以上方法的缺点是: 1)显示速度慢; 2) 内存占用大; 3) 位图在缩小显示 4 l2 R$ Y Z4 w" I6 ?; _# Z
时图形失真大,(可通过安装字体平滑软件来解决); 4) 在低颜色位数的设备上( 9 U |! @; n* x# c9 l/ A
如256显示模式)显示高颜色位数的图形(如真彩色)图形失真严重。
& `. @& C; v) [
! D2 w5 f4 _" v7 d$ \5 N3 c% K1 M# w2 c---- 三、BMP位图缩放显示
. S1 R: L* S: B; w0 \ 1 l1 o& b( ] f V$ \" K. {: \2 y
---- 用DrawDib视频函数来显示位图,内存占用少,速度快,而且还可以对图形
: v/ {4 h: E0 [1 x( H6 f进行淡化(Dithering)处理。淡化处理是一种图形算法,可以用来在一个支持比
0 i& L* S" K$ y$ C4 K2 X7 v$ s3 M图像所用颜色要少的设备上显示彩色图像。BMP位图显示方法如下: ! i2 u- f: M! |; w2 I
2 ~1 Z& w' o l, o" \1 T---- 1. 打开视频函数DrawDibOpen(),一般放在在构造函数中 + F; B0 g" J9 f* a
) ^; F2 G8 S/ k0 X6 ^
---- 2. 申请内存空间用于存放位图文件 ; d8 _+ }5 [/ M2 o$ Z% }
& |( Z& J" c& D! R5 g* o* x2 W( @---- GlobalAlloc(GHND,FileLength); : a( v, R4 O9 f/ d
; r6 Y8 e! y, {
---- 3. 位图文件读入所申请内存空间中
$ b7 U3 J6 b' }+ c3 ^. F % V1 o$ M. {9 x' d0 t+ E2 ?+ _
---- LoadFileToMemory( mpBitsSrc,mFileName);
/ H" z! A" z t
+ I N2 C5 H: o" O---- 4. 在OnPaint等函数中用DrawDibRealize(),DrawDibDraw()显示位图
+ L2 q% A! Z$ F) l' d
! h1 ^0 z7 D) n1 F R. b* C$ R/ v---- 5. 关闭视频函数DrawDibClose(),一般放在在析构函数中 ; V+ L* L0 T' X( A
! _) C! K2 [! _+ C2 ]! A% A* s
---- 以上方法的优点是: 1)显示速度快; 2) 内存占用少; 3) 缩放显示时图形
+ j& X" X' Z1 d/ x! L失真小,4) 在低颜色位数的设备上显示高颜色位数的图形图形时失真小; 5) 通
) ?5 h7 u$ W) M) s过直接处理位图数据,可以制作简单动画。
& R p9 o6 k5 M8 c" V& {% ?5 \ : W# b5 ?& p6 X
---- 四、CViewBimap类编程要点 + N' v$ Z- u' j0 ]/ M& C" c( ?
. J% L/ }% r3 L( N- a, O2 b+ I---- 1. 在CViewBimap类中添加视频函数等成员
) P. S' O+ E$ V6 M / D4 o% K V3 V; J5 `# B
HDRAWDIB m_hDrawDib; // 视频函数 : [0 M5 l$ W. p m
HANDLEmhBitsSrc; // 位图文件句柄(内存) $ n1 i/ _9 o/ F9 M
LPSTR mpBitsSrc; // 位图文件地址(内存)
5 O* a3 W* O* BBITMAPINFOHEADER *mpBitmapInfo; // 位图信息头
6 D( ^9 ?# \1 X+ M3 j: ?6 ] % z5 K5 G2 X3 v8 a5 Z0 [+ O( ~3 Q
7 G2 G; R+ Q* ~1 |/ T4 T
---- 2. 在CViewBimap类构造函数中添加打开视频函数
; `( V9 y8 E9 q6 g& k- p---- m_hDrawDib= DrawDibOpen(); 4 P. K s4 _# [0 }- O2 C! c7 \
5 p# m; W4 y! P" H1 l---- 3. 在CViewBimap类析构函数中添加关闭视频函数
' t. g+ A) ~" B4 y3 F, ?" J" D 7 R+ O" y+ P) h1 t, @# q
if( m_hDrawDib != NULL)
, [" v! \3 j2 b+ K/ \2 H& \4 M {
+ _( Z. a2 O5 H DrawDibClose( m_hDrawDib); ; w q8 I/ m' L: _7 ~
m_hDrawDib = NULL;
" e. ^6 ?" h# V v0 b1 k }
( t7 y: r, N+ j. M& w2 o " w' l# r1 P% H* r
9 B5 [) [! L2 W: F |0 K---- 4. 在CViewBimap类图形显示函数OnPaint中添加GraphicDraw()
8 t$ z( V6 z! I4 u( b1 N. MvoidCViewBitmap::OnPaint() $ c' r6 i+ `+ d% K( Q3 y m7 a [% A V
{
b: I& @* z3 w! }) S5 s) `CPaintDC dc(this); // device context for painting ' H7 {. E+ ^' [# f
GraphicDraw( ); 9 t8 K, ?4 J p" u: W1 j8 z
} . o, b/ d( }/ K: r: `
& k! H/ Q1 W) H! `. M
voidCViewBitmap::GraphicDraw( void ) 2 n3 t' ]6 l/ Q4 ]! Y
{ 4 R( H* t' |; s
CClientDC dc(this); // device context for painting ) K4 F. _! T2 [ L, S
BITMAPFILEHEADER *pBitmapFileHeader; " \8 ]5 ]- G) E* b
ULONG bfoffBits= 0;
8 X9 c+ @& {: v: DCPoint Wid;
4 ~( U u6 j+ ~9 r $ B1 i6 g$ ?4 {8 n3 A# b
// 图形文件名有效 (=0 BMP) 6 k/ ]. Y7 {# N' z; A- z2 ?7 z
if( mBitmapFileType < ID_BITMAP_BMP ) return; 5 ?- N7 q# ]+ ?1 R! }
/ }# \* J8 k( @# U5 `" p: V3 r6 {
// 图形文件名有效 (=0 BMP) " _, T2 r% H' S) }% g" s
// 准备显示真彩位图 + V/ ]& q' Z2 \' e2 F; m9 l
pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;
- b) e" U& R, Q8 N" F) ^1 XbfoffBits= pBitmapFileHeader->bfOffBits; ' G) l7 b$ R* @+ i5 I
9 M0 e1 h a2 ^" e
// 使用普通函数显示位图 1 B4 S) o4 L9 m* y, h( \! V
- b9 n% ~6 w( F% x
if( m_hDrawDib == NULL || mDispMethod == 0)
$ `! O3 n& r! o( u9 c {
' w, N- J( D5 P HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC, ) k s" G' p2 s* L
mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits, # f& I! f- d; p( [: q
(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS); * \7 l; W8 c7 `) V. g8 A' F" s% V
// 建立位图 N: V5 o% i' u$ h& l2 k" K: V
HDC hMemDC=::CreateCompatibleDC(dc.m_hDC);// 建立内存 / k8 K- x3 }9 S5 E& h2 F+ J
HBITMAP hBitmapOld= SelectBitmap(hMemDC, hBitmap); // 选择对象 . ~) ]: t1 Z# D# \0 Z3 t& V
// 成员CRect mDispR用于指示图形显示区域的大小. ! E4 M9 W# s# [+ V. l; l
// 成员CPoint mPos用于指示图形显示起始位置坐标.
# q2 v! x, ]: P+ c& x4 H( sif( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() ))
# o+ ?, L3 `6 |. { y4 ^' gmPos.x= mpBitmapInfo->biWidth - mDispR.Width() ; 1 n5 ^6 F* ]- p3 X7 W& A2 Z
if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height())) 4 l+ {+ \8 |0 s* P0 q; @
mPos.y= mpBitmapInfo- >biHeight- mDispR.Height(); 5 D2 @( _+ a! w, W* r
if( mPos.x < 0 ) mPos.x= 0;
& A- K4 q5 u5 D* A$ E if( mPos.y < 0 ) mPos.y= 0;
" J6 b) B' Q! x2 s5 o
- o3 g- Z1 N% F if( mFullViewTog == 0)
, _8 m+ R# H$ ?3 u& ~( j& @$ _{ & Q4 I1 |. o) X& c# q! \9 Z, d6 P
// 显示真彩位图 + i1 i4 L, l; t
::BitBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),
9 G: f' ~$ `1 KhMemDC,mPos.x,mPos.y, SRCCOPY); 4 N8 k* N+ h3 o5 w+ h# V8 W
} else {
7 M+ Z4 Z0 E2 t0 f h; c$ m7 g::StretchBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),
3 C1 S8 M& I/ B: jhMemDC,0,0, mpBitmapInfo- >biWidth, mpBitmapInfo-
! Y; y$ m! O' V0 I: o>biHeight, SRCCOPY); ) b4 A7 [& l- h" P, G9 z+ o2 r
}
' _; a: m0 Z4 x // 结束显示真彩位图
' D; c* j2 z& e9 H% W9 \ : eleteObject(SelectObject(hMemDC,hBitmapOld));
+ h4 | v2 P$ b! p4 h! ]+ t! v// 删 除 位 图
7 n l7 L7 a& B% |* z/ x } else { 5 i" o& e3 |/ P+ }
! D9 N3 D( R% h. F/ S6 p // 使用视频函数显示位图
( y. J+ H: Q0 L8 k - K" N# I, l( L9 |; u+ ]7 k# h
if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() ))
i- a* a; ^" ?) }! CmPos.x= mpBitmapInfo- >biWidth - mDispR.Width() ; / s( b X# R+ e" q
if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height()))
' H. s% j3 |4 v+ smPos.y= mpBitmapInfo- >biHeight- mDispR.Height(); ' l) I' ~2 I" G$ _
if( mPos.x < 0 ) mPos.x= 0; $ s$ h% [( R l. H. M: G; z% a
if( mPos.y < 0 ) mPos.y= 0; + U( k6 k/ M% v; X. F& E
9 `4 F8 l+ |: r5 @ v' y
// 显示真彩位图 2 K6 U' `4 Z3 _( l) A
DrawDibRealize( m_hDrawDib, dc.GetSafeHdc(), TRUE);
; K: o( J, V6 e+ S5 o; r
0 |2 G3 C7 _* G, c" G if( mFullViewTog == 0)
- h! ^( U/ D& G. Z! g I2 E) W{
0 n3 _3 Z: `2 y2 L+ OWid.x= mDispR.Width();
$ V1 V9 @6 T! fWid.y= mDispR.Height();
$ A, P+ r/ Y9 G' Z1 B// 1:1 显示时, 不能大于图形大小
6 J( a* n: n. Kif( Wid.x > mpBitmapInfo- >biWidth )
& `3 d( I/ c% C( f9 \Wid.x = mpBitmapInfo- >biWidth; 7 ?6 I S: J2 m7 j8 P
if( Wid.y > mpBitmapInfo- >biHeight) 6 [( _8 |" v4 k8 @* h
Wid.y = mpBitmapInfo- >biHeight; : |* C% I; r2 i- f
( _& z" y6 Y; x
DrawDibDraw( m_hDrawDib, dc.GetSafeHdc() 0 T) i( X* D- m9 }3 d3 I
, 0, 0, Wid.x, Wid.y,
! y6 {' I7 W2 K5 gmpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits), 0 n7 B& X! b# G5 R( V
mPos.x, mPos.y, Wid.x, Wid.y, DDF_BACKGROUNDPAL);
5 Q0 }1 n- P* p. X} else { 8 s# q9 l" Z9 Q$ Z
DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(), * C: ~1 w) }6 d* O: \6 E2 o
0, 0, mDispR.Width(), mDispR.Height(),
# ^7 ]5 r$ F& I8 S0 l1 J$ @2 m/ X1 fmpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits), 1 Z9 c; E5 X3 |4 x' W8 G* `( i3 ^9 M
0, 0, mpBitmapInfo- >biWidth, mpBitmapInfo- >biHeight,
- V; m9 T6 p+ [7 S3 R1 A5 ~DDF_BACKGROUNDPAL);
! _! D5 ^; E! @, M}
( j6 ]3 j8 e( ~" p8 F } 0 q6 ^) I- U; V; y" r5 B& L
return; : m9 A1 h& b& K {1 B
} / ~8 U. ^, \0 N
" ^- v; K7 u7 A9 j g, m4 a
1 b! `) c% o. h" d9 m! x---- 五、使用CViewBimap类显示BMP位图 & Z2 k& k' w/ }5 i; w) Q
---- 1. 在Visual C++5.0中新建一个名称为mymap工程文件,类型为MFC R( `) C% q+ g. [
AppWizard[exe]。在编译运行通过后,在WorkSpace(如被关闭,用Alt_0打开)点
+ m7 J+ E- O% F' j- ^) p; a击ResourceView,点击Menu左侧的+符号展开Menu条目,双击IDR_MAINFRAME条目 " E$ R% A- Y5 `7 b
,进入菜单资源编辑,在'“查看(V)”下拉式菜单(英文版为View下拉式菜单)的 q0 q2 P7 Y; f6 N* @- \: ^
尾部添加“ViewBitmap”条目,其ID为ID_VIEW_BITMAP。 1 E5 [ h. Q4 @2 u
- b0 s6 k, G/ ~, W8 d0 n---- 2. 在Visual C++5.0中点击下拉式菜单Project- >Add To project-
6 V0 q9 K: V5 Q1 L3 m% N$ F( h! d>Files...,将Bitmap0.h和Bitmap0.cpp添加到工程文件中。 ( f+ n7 h& C- K- H- T7 b4 b
. u0 {) T* y" w---- 3. 在Visual C++5.0中按Ctrl_W进入MFC ClassWizard,选择类名称为 # V6 N" {$ F6 t! X
CMainFrame,ObjectIDs: ID_VIEW_BITMAP,Messages选择Command,然后点击Add
6 [0 d* P, \ w2 L1 H9 J8 [ Fucction按钮,然后输入函数名为OnViewBimap。在添加OnViewBimap后,在
# O/ O0 @- S! ]1 m7 KMember functions: 中点击OnViewBimap条目,点击Edit Code按钮编辑程序代码 # Y8 [& C- f8 k I4 J; [& R
。代码如下: % p( n, g1 u3 ]( Z
' m" e- G+ Y+ [9 [9 S7 ]
void CMainFrame::OnViewBitmap() 7 w, @1 A5 S. v% A! c+ N
{
( n6 b) {) c% T/ f" O1 K. l x// TOD Add your command handler code here 3 q! C& ? x* [. T9 ^
CViewBitmap *pViewBitmap= NULL; 1 m# b/ C3 z. O2 N! {2 x0 p5 @, I7 B
! s2 U% \* L7 h$ h
pViewBitmap= new CViewBitmap( "BITMAP.BMP", this);
- u- h" T u/ KpViewBitmap- >ShowWindow( TRUE); - k7 s& J$ C1 D! f2 _
}
6 _( ~7 E" k/ R/ V @4 Q
% W" [0 c) H6 @. w& u1 N 1 M0 w3 o( P6 e1 b
---- 并在该程序的头部添加#include "bitmap0.h",然后编译运行。
, ^( C" J% s6 w9 A/ T! R0 F9 {---- 4. 找一个大一点的真彩色的BMP位图,将它拷贝到BITMAP.BMP中。
, j' c' w" G0 v 3 Z+ L% j' z8 v4 E
---- 5. 运行时,点击下拉式菜单“查看(V)- >ViewBitmap”(英文版为View- > - f( O @7 ?4 m- W5 j
ViewBitmap)即可显示BITMAP.BMP位图。 & R& U" S# D# X
: i2 C) p1 ~* G/ }
---- 六、CViewBimap类功能说明
6 z( t% @8 l: Q- X) G
8 K7 Z; L9 f' W' @$ j' J. E/ Y5 A+ L' ?---- 1. 在客户区中带有水平和垂直滚动条。在位图大小大于显示客户区时,可
1 L, U3 [7 x( P3 B/ L2 d以使用滚动条;在位图大小小于显示客户区或全屏显示时,滚动条无效。
1 _9 n+ m8 P: y# H6 W ) @) |- H) E! {
---- 2. 在客户区中底部带有状态条。状态条中的第一格为位图信息,第二格为
1 p4 f! L. Z' A. o7 `( V" Y位图显示方法,可以是使用普通函数或使用视频函数。在第二格区域内点击鼠标 ! e4 v8 }* p* u# k1 k+ ^
,可在两者之间接换。第三格为位图显示比例,可以是1;1显示或全屏显示。在
: i% O+ E2 R1 Y5 M2 C+ b第三格区域内点击鼠标,可在两者之间接换。在全屏显示时,如果位图比客户区 h6 `) w$ n/ r. c% i" ]. n$ W
小,则对位图放大; 如果位图比客户区大,则对位图缩小。
( U5 P7 r1 O( m8 I2 P0 f Q8 w# g
$ h: v) E6 g; e0 C6 b* e---- 3. 支持文件拖放功能。可以从资源管理器中拖动一个位图文件到客户区, - @. m$ Y# R" ?
就可以显示该位图。
! f' g, K5 o# m+ d2 |+ q( w
" B, H+ ~8 o% o3 H5 L; z# ]& V---- 程序调试通过后,可以找一个较大的真彩色位图或调整客户区比位图小,
6 x& ~& h. Z, s, V4 \! z5 [) ?" L1 D8 ~, F( s ?
在全屏显示方式下,比较使用普通函数与使用视频函数的差别。可以看出,位图 ; C# G ~0 u5 F. J' u% U/ D/ }
放大时两者差别不大,但在位图缩小时,两者差别明显; 使用视频函数时位图失
+ w8 P7 |8 V, T) k; P) N( f: V真小,显示速度快。 % @1 R5 e Q" V
7 r5 f. d1 u/ a+ I
---- 还可以从控制面板中将屏幕显示方式从真彩色显示模式切换到256色显示模 & Q, B8 @0 ]% @. B
式,再比较使用普通函数与使用视频函数显示同一个真彩色位图的差别。现在可 8 d* b0 V6 \0 y( ^( {/ x( w
以体会到使用视频函数的优越性了吧。
; s1 L) d) \7 v
- [8 d- \ D- Y$ J; q8 x---- 在全屏显示时,位图的xy方向比例不相同,如要保持相同比例,可在显示 & a6 Q! h8 c9 l1 o* ^+ }* z0 }
程序中加以适当调整即可,读者可自行完成。 |