|
) N) V2 i- C. g* H# j6 a1 O' m+ w
西安交通大学流体机械研究所 " r! O1 W# v1 z3 h" l1 S
张义云 . F2 X# }( q {; z7 }2 r+ r- o
4 V8 k* Z: [, D2 _1 u) T$ a
---- 用普通方法显示BMP位图,占内存大,速度慢,在图形缩小时,失真严重,
% T c; i# R4 g, I& X在低颜色位数的设备上显示高颜色位数的图形图形时失真大。本文采用视频函数 / o4 O' b2 q" q8 B
显示BMP位图,可以消除以上的缺点。
$ N% _) d0 m& r) s* u/ [
% j6 k: M3 n3 S7 S+ c---- 一、BMP文件结构 * \. `# j4 n) O }- L0 m
7 Q, `4 v# ?6 y6 |- J0 M
---- 1. BMP文件组成
# [$ g& d( r" H$ Q % K% a7 `) r# s; M9 X1 u" Z, w/ N
---- BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。 1 |( k2 o" ~7 T) c# x5 ?/ G8 \" \
) z8 ~2 O. g6 R4 T7 `( |: n
---- 2. BMP文件头
J, J0 u/ R0 H: {/ j
+ \0 ^- w: G8 y: {& Q d" V* P---- BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息
7 B) f3 ]/ n3 v。
. Q! z" M. `/ D! S9 ?- L- r( t 5 q- E- S7 c! T
---- 其结构定义如下:
" p3 Y7 |& c F' Z" r * H# K6 V3 A0 i0 ~2 Q' x" s
typedef struct tagBITMAPFILEHEADER & N) G/ E5 @4 o# y9 F2 e* S
{ , ?0 z- R5 H& {
WORDbfType; // 位图文件的类型,必须为BM * d% ]7 r1 h y# m
DWORD bfSize; // 位图文件的大小,以字节为单位
7 j5 R* R) G& _ u2 ]WORDbfReserved1; // 位图文件保留字,必须为0
5 P4 {2 S7 ^6 f# Y, `+ K7 q bWORDbfReserved2; // 位图文件保留字,必须为0
8 e# r1 `5 h) i: DDWORD bfOffBits; // 位图数据的起始位置,以相对于位图 & h! | e- a" W
// 文件头的偏移量表示,以字节为单位
0 {% C f$ F* ?6 x: f7 i9 v' |. i} BITMAPFILEHEADER; ' M8 ~( ] h- j7 x0 I% g3 z: e" c+ k
% J( `' S1 P$ o. h
3 W; W, Q" H0 M7 B1 ? q' r$ f) A: A---- 3. 位图信息头
5 Y6 u: B5 k2 g& {" u' j, V----
% G( A: y) B9 _8 { 4 B2 ?6 \2 b" e9 v5 i) ^& X
BMP位图信息头数据用于说明位图的尺寸等信息。 $ j h" V6 D. |8 N
typedef struct tagBITMAPINFOHEADER{
6 Z2 I9 a, a0 V. ~5 O& x$ Z DWORD biSize; // 本结构所占用字节数
, K. ?1 l6 p7 t; }! I LONGbiWidth; // 位图的宽度,以像素为单位
0 x s( ^2 n: q- I: L LONGbiHeight; // 位图的高度,以像素为单位
4 f8 Z L5 k9 w0 m( L# w4 G7 c) i: j WORD biPlanes; // 目标设备的级别,必须为1
6 \1 m" b+ H# U, p WORD biBitCount// 每个像素所需的位数,必须是1(双色), 0 [4 j6 H" r: F) I) [. ]4 u4 U
// 4(16色),8(256色)或24(真彩色)之一
/ V, ]' S* F& N DWORD biCompression; // 位图压缩类型,必须是 0(不压缩), % d3 f: S/ k! G9 Z0 f, b0 W
// 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
8 L8 C& X" I/ d/ c DWORD biSizeImage; // 位图的大小,以字节为单位 ; c; ~0 T# ^( {- a ~$ y7 W
LONGbiXPelsPerMeter; // 位图水平分辨率,每米像素数 # S* y/ N7 O9 |9 x0 @2 L; ^. D9 b$ p
LONGbiYPelsPerMeter; // 位图垂直分辨率,每米像素数 $ r. m- R) V" ^. v' i8 Z$ Y* M
DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数
$ }# J# v8 L2 p/ ~. K% }4 X DWORD biClrImportant;// 位图显示过程中重要的颜色数
& f1 }" L! i8 E) {0 s} BITMAPINFOHEADER; ; e% q. b' {0 T! ^
1 q! K6 A0 B7 u B/ A
5 c0 {! _( [" C. n) f% a1 _---- 4. 颜色表 2 H# o$ w2 ^% D, @2 c
---- 颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个 7 a! q5 x6 H8 J! x" a
RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下: 3 s9 }& M2 D% h1 U% k* D* p7 k
( m% A: E! w( t. z7 W1 P
typedef struct tagRGBQUAD { $ H+ P5 `1 i- j( G$ G7 g
BYTErgbBlue;// 蓝色的亮度(值范围为0-255) # w' n' q9 T/ E# r; r& h
BYTErgbGreen; // 绿色的亮度(值范围为0-255)
" h A) b6 Q) ?) UBYTErgbRed; // 红色的亮度(值范围为0-255)
4 A' q$ o% v% Q# p* J5 H. jBYTErgbReserved;// 保留,必须为0 " |6 K3 D# _+ A, ]% p
} RGBQUAD;
* p8 x# }0 Z# h0 p2 t v颜色表中RGBQUAD结构数据的个数有biBitCount来确定: $ M2 g5 q1 A+ ^4 I
当biBitCount=1,4,8时,分别有2,16,256个表项;
0 z8 p" ^& X0 r1 ~当biBitCount=24时,没有颜色表项。 ; c/ u6 n R1 e! [# ]5 F' J# {
位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下: x1 B7 Z1 F5 w; u5 w+ a
typedef struct tagBITMAPINFO {
% N5 M) R( \6 f+ p& u# k BITMAPINFOHEADER bmiHeader; // 位图信息头 9 ?1 I1 ?5 R, w2 j
RGBQUAD bmiColors[1]; // 颜色表 , m' k* j0 f! {& `4 z8 ]: N
} BITMAPINFO;
) }6 @0 H6 \, s3 R. d
2 d* d9 V% U' n4 g8 C) c! C8 R + ^) D* U! ?: n* o7 l
) S4 t' P5 a6 c! d9 Y/ z---- 5. 位图数据
5 ~" h6 k8 i4 g% X& V. `. w* W---- 位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右 ! n5 }3 m. i/ ^# }& ~8 z
,扫描行之间是从下到上。位图的一个像素值所占的字节数: 2 a' q+ a. O2 d# O, I
6 O1 E- g6 \% j8 d6 f当biBitCount=1时,8个像素占1个字节;
/ U0 B2 y; _" X4 Z5 K( p6 Z! E4 P当biBitCount=4时,2个像素占1个字节;
5 J6 M# W; W- }) f: D, f$ V3 g5 R4 \' s当biBitCount=8时,1个像素占1个字节; 4 V D E& T2 I2 f+ W: f
当biBitCount=24时,1个像素占3个字节; * E/ m0 F* f x2 ~! x! w
Windows规定一个扫描行所占的字节数必须是 " s4 [2 [/ o& i! h. Z5 G
4的倍数(即以long为单位),不足的以0填充, , @ M4 k( L5 J/ m. Q8 W
一个扫描行所占的字节数计算方法: 6 i, h* C( ^. r4 v! M
DataSizePerLine= (biWidth* biBitCount+31)/8;
1 k3 ]2 ?! L* s // 一个扫描行所占的字节数 - A a" K/ x$ D6 ^5 Z. S- h% g
DataSizePerLine= DataSizePerLine/4*4; // 字节数必须是4的倍数 : M4 U9 x4 i0 ^* A1 E! P. u" G$ A
位图数据的大小(不压缩情况下): 0 x/ g- v& t5 j8 v. g
DataSize= DataSizePerLine* biHeight;
+ C: V' Q3 ]2 h) V0 k+ m9 H1 S8 }
6 h7 g& U% {/ l S' Y( H * j; n: D/ b* K% L, j5 j
---- 二、BMP位图一般显示方法
9 Z, i; ^5 N5 R6 A# F" x---- 1. 申请内存空间用于存放位图文件 6 k, m" o2 v% r+ O
y3 q( k: n/ C" b# Z* C( ?
---- GlobalAlloc(GHND,FileLength);
" c" {( f; U \. `6 M6 g
) V* {; P- h; s" K. W. i4 u/ y---- 2. 位图文件读入所申请内存空间中 " N9 ^4 ~/ K6 z. P! J/ }8 P3 A
; H$ J$ C* E3 _3 F# }7 ?/ Z6 z4 F
---- LoadFileToMemory( mpBitsSrc,mFileName);
; Z/ V2 L, t' H C Q. s/ g+ h1 H
$ N1 s/ v% n/ h: f---- 3. 在OnPaint等函数中用创建显示用位图 ' \' d2 T9 m, {) {4 L
5 p, J% L2 S! U! A2 T
---- 用CreateDIBitmap()创建显示用位图,用CreateCompatibleDC()创建兼容
' n m$ h. w# X- fDC,
& Q9 l; M. v2 I( A5 b 3 E. N4 v4 V. P& l0 }- G( r% u9 ~# F2 X
---- 用SelectBitmap()选择显示位图。
* p4 ] O9 A; ~* W# ^- H# Y/ \ " o4 W1 G' p$ O9 s2 }8 B
---- 4. 用BitBlt或StretchBlt等函数显示位图 ) J( L; f$ V: ^. J; o1 q
7 p- ]3 q8 @) c0 e; ], J/ I; V$ [9 j
---- 5. 用DeleteObject()删除所创建的位图
+ E! n# Z) C7 a: m! b" } O. e3 A+ N9 J
/ |0 p3 H& D8 R---- 以上方法的缺点是: 1)显示速度慢; 2) 内存占用大; 3) 位图在缩小显示 : D) S; E* D- j5 f3 s# R
时图形失真大,(可通过安装字体平滑软件来解决); 4) 在低颜色位数的设备上(
& w% {! Q; f8 D1 T, t# F2 |& j如256显示模式)显示高颜色位数的图形(如真彩色)图形失真严重。 ' l# P5 M/ y7 ?3 n+ T5 L- V5 j; m
* S7 [. @1 W! r) y( f1 ^1 [
---- 三、BMP位图缩放显示 ! O1 s7 G. n: E9 Z; q) N# a
7 E% X8 x. n2 P$ f \0 H
---- 用DrawDib视频函数来显示位图,内存占用少,速度快,而且还可以对图形 5 ]3 ^3 Q1 [( i) y4 o3 V+ q7 p
进行淡化(Dithering)处理。淡化处理是一种图形算法,可以用来在一个支持比
+ d5 H; k# u' [- _图像所用颜色要少的设备上显示彩色图像。BMP位图显示方法如下: 6 [8 q6 u# d5 E
, ^3 W8 L. [, Q4 M---- 1. 打开视频函数DrawDibOpen(),一般放在在构造函数中
# o5 J9 d( C' }( S2 a& ~
" ?8 j6 p; c3 I) N3 d: B) @! S---- 2. 申请内存空间用于存放位图文件 " R5 P& L* R0 M' p8 o
7 @- \* _0 l. w' _# a$ v
---- GlobalAlloc(GHND,FileLength);
5 |- q) N4 S5 h& j# X% {& |! i d
' c) r4 C; y) u( }( G' \$ b---- 3. 位图文件读入所申请内存空间中
2 q7 l5 D) D- h9 M1 M0 m % h5 H, p5 q+ e' x# U
---- LoadFileToMemory( mpBitsSrc,mFileName);
- S4 S n. b U% F( Y0 P
9 Y* m1 p8 h5 p+ u: Q) S# R---- 4. 在OnPaint等函数中用DrawDibRealize(),DrawDibDraw()显示位图
8 r6 }; f$ F0 F8 f5 C/ c
0 f( [5 } ?. x% B---- 5. 关闭视频函数DrawDibClose(),一般放在在析构函数中 $ S6 n7 _! a5 m. D5 y
. _& g5 X# ]8 ~' L: i- Z---- 以上方法的优点是: 1)显示速度快; 2) 内存占用少; 3) 缩放显示时图形 2 o+ `8 I( Z+ J+ y6 b
失真小,4) 在低颜色位数的设备上显示高颜色位数的图形图形时失真小; 5) 通 & i& ?/ c# [. p" l" M
过直接处理位图数据,可以制作简单动画。
( ]8 L1 o. v9 m$ f/ c& O " g6 n5 o+ I j1 @+ n0 C& u! L
---- 四、CViewBimap类编程要点 9 d# Y( d& A0 G
9 N2 H: \ T6 z* h
---- 1. 在CViewBimap类中添加视频函数等成员 & }0 |$ O+ |, k! z: c' j) f4 q0 K
" z, X4 Z3 L- J- mHDRAWDIB m_hDrawDib; // 视频函数 i0 x+ n/ K6 o
HANDLEmhBitsSrc; // 位图文件句柄(内存)
% u; d% _( O; }( c+ R1 x, jLPSTR mpBitsSrc; // 位图文件地址(内存)
6 `0 M. ~% t# h) S* a0 M N, H5 Q- dBITMAPINFOHEADER *mpBitmapInfo; // 位图信息头
4 E3 r* [ s3 q6 Y
+ W/ t0 p9 z* N& ? l2 \ # T+ F; `& i) N' x: K% f4 E
---- 2. 在CViewBimap类构造函数中添加打开视频函数 : j% y5 ~7 o3 a5 _' B
---- m_hDrawDib= DrawDibOpen();
0 j! w1 Q- E: [( `! e7 n% T - j$ J* |; C2 Q' C+ e
---- 3. 在CViewBimap类析构函数中添加关闭视频函数 / m5 H0 G: T* J& m9 a$ m
6 ?+ b* ^5 ]. y( I" F
if( m_hDrawDib != NULL) : Z. k R2 Q3 i: F" I* n$ e/ h
{
: [( Q [. g C, w9 u) H DrawDibClose( m_hDrawDib);
6 d- R Z1 e1 R w2 A m_hDrawDib = NULL;
+ L% G. b! Q3 _9 F' |: _. K } ( Y% g* h9 a n" s# _% Z% v$ L
/ o9 |9 ?& V& j ; m; D, B2 i$ {5 Y7 X7 G
---- 4. 在CViewBimap类图形显示函数OnPaint中添加GraphicDraw()
) U/ \6 m5 Q# u- H! M, WvoidCViewBitmap::OnPaint()
2 \) n K* _+ u{
! S- r1 X/ C% ]# j% p. j' MCPaintDC dc(this); // device context for painting
1 c3 v9 U7 }& o) ~2 s% QGraphicDraw( ); $ U J ^6 c/ w( u2 d& V5 Z
} - O. a' ^6 D1 {& S
: k/ N1 u& |- D% n4 i9 {% VvoidCViewBitmap::GraphicDraw( void ) 4 E0 b3 ~1 ]: W1 h; _6 g# }
{
$ U8 s" X- L/ E; TCClientDC dc(this); // device context for painting
* l6 n0 P/ J0 A: mBITMAPFILEHEADER *pBitmapFileHeader; ! U/ |& T8 X' q' Q z; s( K( ~7 v8 P* L1 J
ULONG bfoffBits= 0;
5 p9 G5 Y9 }9 d- c4 t8 D' n: D" y$ R" uCPoint Wid; 9 r) E3 N; \' P: x9 D: T
; ~/ ~, a. a# {% s1 \1 S% S
// 图形文件名有效 (=0 BMP) 1 M2 k7 E$ A/ h1 j
if( mBitmapFileType < ID_BITMAP_BMP ) return; . C6 r/ g- r' c
2 |0 j0 r2 p& [, W
// 图形文件名有效 (=0 BMP) 4 U8 c- M+ U; G
// 准备显示真彩位图
. E2 z3 }5 @2 ypBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc; 1 m+ ^0 I* c! |% @ S0 @
bfoffBits= pBitmapFileHeader->bfOffBits; + l( s' q# q. i, X b' W
. g- F9 q5 k) C, c/ H: e3 c
// 使用普通函数显示位图
/ V/ T, [ }$ A
( Z, i/ J& I" L; g% oif( m_hDrawDib == NULL || mDispMethod == 0)
; \+ Y* F0 Z8 o0 ] { 0 y7 o, f$ x+ A/ w
HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC, ; ?$ e' a9 n3 C
mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,
8 k1 @) ~. b' O$ [; N (LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS); Q/ q$ A! n7 ]& @4 d
// 建立位图
; [# P; P; I- r$ ]HDC hMemDC=::CreateCompatibleDC(dc.m_hDC);// 建立内存
1 D* `2 e8 g; bHBITMAP hBitmapOld= SelectBitmap(hMemDC, hBitmap); // 选择对象 9 h& {# J4 ~3 R3 `
// 成员CRect mDispR用于指示图形显示区域的大小.
$ n, p% y2 s: z+ f9 b// 成员CPoint mPos用于指示图形显示起始位置坐标. ; K; v8 F# h" I5 Q# ^* D
if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() )) , K: e1 N z9 q8 ?
mPos.x= mpBitmapInfo->biWidth - mDispR.Width() ; 2 V3 h) [, C) Q$ |& y( Y; I0 f
if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height()))
% I( r. ^4 j! _- I* S% A6 t) N& omPos.y= mpBitmapInfo- >biHeight- mDispR.Height();
/ m! D! z; W; p$ l3 N' y if( mPos.x < 0 ) mPos.x= 0; / H5 c8 x. k8 \% i- b, ?
if( mPos.y < 0 ) mPos.y= 0;
& ]7 N4 x. K# ~; c
! a, L1 P3 W& F, A: I6 Y if( mFullViewTog == 0)
5 |& A& f) P$ L T9 @' Z' w2 D" v{
: F: b5 D" [. U) G T5 H// 显示真彩位图 ( i9 o7 H/ \& j. M9 H* {
::BitBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),
7 }- |6 T) d9 ~3 J& z$ WhMemDC,mPos.x,mPos.y, SRCCOPY); 1 R1 y! _( @2 J; U5 }4 A4 M3 c
} else {
( I! _& m8 s, O, {::StretchBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),
/ K G1 F$ v2 U( e3 f1 jhMemDC,0,0, mpBitmapInfo- >biWidth, mpBitmapInfo-
5 c$ a$ p& g- q- |7 Q( C>biHeight, SRCCOPY);
/ E7 G' M. a1 `. t' d}
4 t! n0 l1 ?4 ~' [: V j // 结束显示真彩位图
" w2 X5 D$ s% r4 A" n+ U : eleteObject(SelectObject(hMemDC,hBitmapOld)); 8 U- D( Z, M; E5 x
// 删 除 位 图 1 F2 m) D' o7 c1 A
} else {
) n+ V! w; T8 A' u! k; O8 x/ R * [8 e6 B& Z( U6 d* t) E
// 使用视频函数显示位图
' d6 l" E5 I- I# d * r2 Y( e4 D) |5 Q3 X# }
if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() ))
9 u' k8 x. i* P2 e& z2 {mPos.x= mpBitmapInfo- >biWidth - mDispR.Width() ; $ S& r( t( {7 ^
if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height())) $ w. E0 L" E3 k$ A
mPos.y= mpBitmapInfo- >biHeight- mDispR.Height(); ( V/ I8 y" n9 b6 k
if( mPos.x < 0 ) mPos.x= 0; / F( D8 n2 M7 S
if( mPos.y < 0 ) mPos.y= 0; {+ y: p3 b0 r+ j8 C( |: k
$ P5 E" i& j6 h M
// 显示真彩位图 3 M" z1 F/ ?& g/ X0 ]0 ], X' e
DrawDibRealize( m_hDrawDib, dc.GetSafeHdc(), TRUE); & E0 N" N& \' I+ g- H8 z) U$ l) K0 `
* J7 W- T: A$ Z5 b$ U8 C if( mFullViewTog == 0) ; I+ t% x D b6 g" w2 F0 L
{ ; U) T: v$ Y2 ]1 v4 z
Wid.x= mDispR.Width(); / c. o, |4 H1 {9 Q0 j) B: M* C2 `1 _
Wid.y= mDispR.Height();
: @2 O' ~- T& m9 z$ d// 1:1 显示时, 不能大于图形大小
" A3 j& T: g# G) N6 ^# Yif( Wid.x > mpBitmapInfo- >biWidth ) " \8 d. d7 ?, F
Wid.x = mpBitmapInfo- >biWidth;
3 E( l& K' N$ G+ Y* I' jif( Wid.y > mpBitmapInfo- >biHeight)
" p) l6 E6 k9 C: iWid.y = mpBitmapInfo- >biHeight;
( ~! J: e5 Z& X: W7 I; O
1 V9 L4 d7 `- w& {- tDrawDibDraw( m_hDrawDib, dc.GetSafeHdc() : ^+ S0 ^# ]( M6 x, A
, 0, 0, Wid.x, Wid.y, - o( P+ Y/ v& g2 j
mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),
; B6 j( d1 s* T; xmPos.x, mPos.y, Wid.x, Wid.y, DDF_BACKGROUNDPAL);
; L" f" C% @& K, c6 ^0 f# n" ]} else { % I0 A/ D! `& U; j5 o& e
DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),
6 ^! v3 O" Z, b, {0, 0, mDispR.Width(), mDispR.Height(), 5 B0 c" Q) j1 c3 S$ y- b
mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits), ) A# ?9 f+ c4 z0 L' }, C
0, 0, mpBitmapInfo- >biWidth, mpBitmapInfo- >biHeight, : p t8 y3 |" C" P8 g. g q8 \
DDF_BACKGROUNDPAL);
p- |4 l) z, w3 a2 w% [- R, t/ |4 ]7 l}
. i6 z9 `! ^2 x* [; j. c( ~ }
4 X! g/ f# Z/ i& o: ]6 Yreturn;
4 q/ l; s* s+ r}
7 n% M' l+ g& c* }2 ~, y& u 4 z4 F. }# g+ b; R; x/ w
+ v2 W2 q/ \! A4 T1 w---- 五、使用CViewBimap类显示BMP位图
9 r3 E& d. L3 K3 A---- 1. 在Visual C++5.0中新建一个名称为mymap工程文件,类型为MFC 6 B% Y }: `# l9 t# C: {
AppWizard[exe]。在编译运行通过后,在WorkSpace(如被关闭,用Alt_0打开)点 5 F/ V# c1 A! _; C5 @1 {
击ResourceView,点击Menu左侧的+符号展开Menu条目,双击IDR_MAINFRAME条目 ! c% @6 z/ r0 v6 t' \9 z' w
,进入菜单资源编辑,在'“查看(V)”下拉式菜单(英文版为View下拉式菜单)的
9 @+ P3 n1 d4 L7 C6 ?$ C L尾部添加“ViewBitmap”条目,其ID为ID_VIEW_BITMAP。
& z \" @; A6 u. X/ t% q) x * c2 q4 t2 ?3 U# d3 n
---- 2. 在Visual C++5.0中点击下拉式菜单Project- >Add To project- c! t6 I( D& ^0 D/ a8 T
>Files...,将Bitmap0.h和Bitmap0.cpp添加到工程文件中。
0 V J0 }# k- ^5 L - }" r6 w! x; k: k7 S
---- 3. 在Visual C++5.0中按Ctrl_W进入MFC ClassWizard,选择类名称为
# r( c5 J8 l' e D1 J$ c. |CMainFrame,ObjectIDs: ID_VIEW_BITMAP,Messages选择Command,然后点击Add 4 P2 a( c w+ t- d. U6 p
Fucction按钮,然后输入函数名为OnViewBimap。在添加OnViewBimap后,在 % X, q, a" b* w
Member functions: 中点击OnViewBimap条目,点击Edit Code按钮编辑程序代码
5 f; Z% K+ _' V! N( v& y。代码如下:
N6 l1 _- A" v: d3 u$ z+ l( Z
: D }1 D7 T5 M" a, v" }* U mvoid CMainFrame::OnViewBitmap() 3 j( J* }# C* `- K! T0 ?( N5 Z
{
7 H& M/ Y9 \* s: V* p// TOD Add your command handler code here
9 Z; w9 S- w7 W) A# S5 @CViewBitmap *pViewBitmap= NULL;
. T& `/ y) ~0 P. O" n' T. ]
2 l }1 V2 ^. L2 bpViewBitmap= new CViewBitmap( "BITMAP.BMP", this); % z, L/ ^" k$ p
pViewBitmap- >ShowWindow( TRUE);
7 v/ q4 g5 z# G/ V" s5 @, I3 j$ c} * p1 K e- y" g
3 ^/ M% o1 u3 z9 h$ u0 H
7 F& [" w$ ] }---- 并在该程序的头部添加#include "bitmap0.h",然后编译运行。
, h0 a/ h( g2 f* m---- 4. 找一个大一点的真彩色的BMP位图,将它拷贝到BITMAP.BMP中。 & {- i5 _! l J* ?
V' u8 \. I) b3 s0 \
---- 5. 运行时,点击下拉式菜单“查看(V)- >ViewBitmap”(英文版为View- > 2 y5 L, F5 U7 B3 p8 c
ViewBitmap)即可显示BITMAP.BMP位图。
, Q- q6 }/ o+ T/ v! d- ]
% M9 z3 A, p0 b% a# v' n! |/ ^---- 六、CViewBimap类功能说明
/ x K5 n% K1 `* ^ ) ]$ [* n/ y5 h1 E; {1 P
---- 1. 在客户区中带有水平和垂直滚动条。在位图大小大于显示客户区时,可 - N) Z$ g& [3 a
以使用滚动条;在位图大小小于显示客户区或全屏显示时,滚动条无效。 1 Q* @7 T) n3 x! b
1 E1 Q2 F/ R2 ^* ?/ S7 ]. m---- 2. 在客户区中底部带有状态条。状态条中的第一格为位图信息,第二格为 7 g. H4 i8 a8 o0 p
位图显示方法,可以是使用普通函数或使用视频函数。在第二格区域内点击鼠标
% o: p' e0 v1 ~4 x4 F# z,可在两者之间接换。第三格为位图显示比例,可以是1;1显示或全屏显示。在 * a5 g, }" L% v6 E) Y& p3 C; p
第三格区域内点击鼠标,可在两者之间接换。在全屏显示时,如果位图比客户区 4 G& B ^: E" F$ O- z
小,则对位图放大; 如果位图比客户区大,则对位图缩小。 2 v% s; O% I: {) r1 v3 a
1 ?0 R. l% [3 C0 Z* B5 \---- 3. 支持文件拖放功能。可以从资源管理器中拖动一个位图文件到客户区,
6 f. \$ E: g' E! H3 X5 l就可以显示该位图。
5 H9 `0 [( {1 x & [, Q* f, }, _
---- 程序调试通过后,可以找一个较大的真彩色位图或调整客户区比位图小,
) @5 O: g" v8 g
8 ~" F1 h" G: u在全屏显示方式下,比较使用普通函数与使用视频函数的差别。可以看出,位图
7 k: g9 x& n/ G* f4 t5 |( h+ G放大时两者差别不大,但在位图缩小时,两者差别明显; 使用视频函数时位图失
+ G3 r4 z1 P1 _) m% D( `真小,显示速度快。
. S( ?; S; l5 F; G! A. h/ V4 o/ J
7 t1 M( E6 l! Q' e: l$ m, d---- 还可以从控制面板中将屏幕显示方式从真彩色显示模式切换到256色显示模 `3 \7 ~' f& Y0 y Z4 O
式,再比较使用普通函数与使用视频函数显示同一个真彩色位图的差别。现在可
, D- E9 z( j# G5 {) j以体会到使用视频函数的优越性了吧。
/ z0 j; C) }! E; {
' }- G& t, e6 T+ }! N! t---- 在全屏显示时,位图的xy方向比例不相同,如要保持相同比例,可在显示 . X; [3 C) }- Q- o6 M7 {8 k
程序中加以适当调整即可,读者可自行完成。 |