|
! Y( j; j. y% w8 d7 M- @5 f! k8 ~% @西安交通大学流体机械研究所 * e& n& T8 d% Y: C, \
张义云 * S5 I {8 u/ t- h/ J4 w8 s* s( J* ~
0 P; U5 ~4 N" D6 E# H d8 b$ Q, t! `* `
---- 用普通方法显示BMP位图,占内存大,速度慢,在图形缩小时,失真严重, ) }; p7 f* z4 m% d! I$ u+ Q
在低颜色位数的设备上显示高颜色位数的图形图形时失真大。本文采用视频函数 $ U. `( S) A. H2 A5 ^, p
显示BMP位图,可以消除以上的缺点。 8 H1 I! }) S L+ x( m( ]2 _4 R- d
- h! {( X$ R. Z! r7 g# p---- 一、BMP文件结构 + d6 ^- i5 y v: Z' M# Y
9 q8 V) a W1 [4 W# y---- 1. BMP文件组成 7 z3 l* F" I0 |
# k& ~* x! d O/ u0 |---- BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。
7 n0 t' z$ Q0 X% b9 i
/ P( s" b! y# ]/ B S+ S---- 2. BMP文件头 8 d5 |1 S5 V4 X/ S! x
+ Z3 u+ q& K/ r' N- N---- BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息 $ @7 D& X5 \: p, K$ u# @ p2 h) k' n
。
; l: g% B" O: s. @! {( k
1 x9 ~% q7 k. N, [: {---- 其结构定义如下: + a! R- m9 Z( t0 v' j
@5 g5 T4 U9 ytypedef struct tagBITMAPFILEHEADER ' _& @4 N! Q: W* a1 o) \- b
{
' d8 y* p2 e! V( q, [WORDbfType; // 位图文件的类型,必须为BM 4 A4 I% @; ]( p
DWORD bfSize; // 位图文件的大小,以字节为单位 9 K0 S3 O8 Q- i- `, d3 t8 T0 h3 n
WORDbfReserved1; // 位图文件保留字,必须为0 : g+ w& v/ T9 u$ A1 K
WORDbfReserved2; // 位图文件保留字,必须为0 . L- l$ y( J5 V, @
DWORD bfOffBits; // 位图数据的起始位置,以相对于位图 X8 q/ `% C2 r
// 文件头的偏移量表示,以字节为单位
9 ^! G1 `& W3 I) w% s} BITMAPFILEHEADER;
9 m9 p1 W& R8 Z$ w+ b$ a ' k! l" M7 M8 @6 a
8 T3 a. u# {1 g( ?* r: D8 Q+ T---- 3. 位图信息头
- ~9 v2 H( k: h6 ?( |---- - ?( _1 q6 w3 Q: Q6 \) ]9 H7 W
. d- e4 e( K8 t. u, P) Y$ ]BMP位图信息头数据用于说明位图的尺寸等信息。
8 a5 u7 F; D r- Z5 E# E5 Ztypedef struct tagBITMAPINFOHEADER{ 9 S: G% A) }8 x0 y
DWORD biSize; // 本结构所占用字节数 2 P$ N: e6 i- F1 K# y3 p/ A5 ?, p
LONGbiWidth; // 位图的宽度,以像素为单位
: K8 g3 T g r LONGbiHeight; // 位图的高度,以像素为单位
" d6 ]) T, t; W* n5 J WORD biPlanes; // 目标设备的级别,必须为1 " g* c$ `/ h, E: t; z% u
WORD biBitCount// 每个像素所需的位数,必须是1(双色),
" _* U5 d% @6 e, `+ C+ K // 4(16色),8(256色)或24(真彩色)之一 6 l$ ?8 W1 a J( P+ B
DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),
9 W/ ]' t8 s1 Q- K0 {; J // 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
' K3 S5 b# y. _% V) p2 O& P DWORD biSizeImage; // 位图的大小,以字节为单位
2 q1 ]$ s# A' Z6 \ LONGbiXPelsPerMeter; // 位图水平分辨率,每米像素数 8 n4 o9 b& V' [8 q
LONGbiYPelsPerMeter; // 位图垂直分辨率,每米像素数 / a+ @5 j2 x1 r( D2 g
DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数 5 r+ J+ U5 {4 S) M
DWORD biClrImportant;// 位图显示过程中重要的颜色数 2 g- d9 C0 ]5 X% g3 X3 r/ [
} BITMAPINFOHEADER;
. y j. j/ Q2 f2 d! M
+ Q! ^4 [. `' K+ h# }+ t
0 n% b; Y! y7 L$ Z---- 4. 颜色表 ; j$ Q2 N1 u2 ^# ?( K
---- 颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个 ( ]0 Q1 y8 l) h2 H7 h2 r
RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:
! M2 _0 v) Q; K5 V
& H& Z. z% L' N1 {typedef struct tagRGBQUAD {
% z4 v z `* \; D' h7 G- DBYTErgbBlue;// 蓝色的亮度(值范围为0-255) 8 `; ^2 K2 }9 h0 {. _ q
BYTErgbGreen; // 绿色的亮度(值范围为0-255)
* X6 L% N, G- I5 P7 S8 C l" EBYTErgbRed; // 红色的亮度(值范围为0-255) 3 ^8 b3 e0 K1 @
BYTErgbReserved;// 保留,必须为0 + w3 v# H" z+ w y" [
} RGBQUAD;
6 b* S/ h$ K" g$ a, z+ }颜色表中RGBQUAD结构数据的个数有biBitCount来确定: / A6 f1 Z! d( M4 v3 W! \
当biBitCount=1,4,8时,分别有2,16,256个表项;
4 r/ M! M% n# M# d& T当biBitCount=24时,没有颜色表项。
3 L( h; w: D# ~4 m3 n: P# ^ 位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:
9 P( }( |0 G2 v, L$ f7 i' wtypedef struct tagBITMAPINFO { 6 h5 j4 K! n% w) `
BITMAPINFOHEADER bmiHeader; // 位图信息头 : {3 I% e4 z" ~" l( ^0 ]8 f# R. l
RGBQUAD bmiColors[1]; // 颜色表 - h% e) N: C' `+ T
} BITMAPINFO; 2 c' t6 N' X, ?7 n6 d( S
" i' ^% V2 M+ Z1 o; j. z
( y g; j" w5 M0 w
" q# d8 }2 s- f1 ~% S$ M8 v4 B---- 5. 位图数据 $ q( `# L) `/ Z" }! C) \
---- 位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右 8 C! |4 S' i/ ~) Z) v
,扫描行之间是从下到上。位图的一个像素值所占的字节数:
; y) f, Y! j, M% R6 p; q2 x8 ~ % L4 k9 f, q( R0 j" c
当biBitCount=1时,8个像素占1个字节; 2 v7 ]' @. Y6 \! t5 i+ P
当biBitCount=4时,2个像素占1个字节; ' d( @4 _4 ^0 t2 N: { G! U
当biBitCount=8时,1个像素占1个字节;
( U7 i( \9 ^' {当biBitCount=24时,1个像素占3个字节;
4 v% ^# x/ F7 e$ pWindows规定一个扫描行所占的字节数必须是
, s) e7 x7 V# |6 _7 t2 h1 d4的倍数(即以long为单位),不足的以0填充,
' P3 E! l5 s6 e! N一个扫描行所占的字节数计算方法:
5 q3 t. g6 j7 i( C" c! ]DataSizePerLine= (biWidth* biBitCount+31)/8;
q. k; ]6 X k3 C: I! u3 X0 v! X // 一个扫描行所占的字节数
) B) m/ ?* a ^, r( h) Q( F; C6 Y# hDataSizePerLine= DataSizePerLine/4*4; // 字节数必须是4的倍数 5 g7 l* B5 g3 A! v9 Y# H0 s* S. Y
位图数据的大小(不压缩情况下): - K- S8 ]. Q# ]3 f$ s3 O
DataSize= DataSizePerLine* biHeight; ' t5 H" g- u8 Y8 D' ]) T
0 U. O5 {" Q& S: n% n! w
- V0 A3 `/ C9 n' w6 C8 O8 ]---- 二、BMP位图一般显示方法 0 B% M+ ^# r: \; a( B
---- 1. 申请内存空间用于存放位图文件 8 X( Z @8 ?, N, e8 t% J
0 Y/ X/ a$ E+ a+ {6 D- i
---- GlobalAlloc(GHND,FileLength);
8 F& s9 t: g) k) `1 l2 {
, A+ ^# a( H' b/ L l---- 2. 位图文件读入所申请内存空间中 0 V& D9 H) r, w; v
6 J% W* `$ K) E) ?6 O7 b5 @---- LoadFileToMemory( mpBitsSrc,mFileName);
9 K; Z( n @2 H. |, B ; ~9 b% Y) S% d" u
---- 3. 在OnPaint等函数中用创建显示用位图 - v2 j+ l. L# J X9 H
9 M( ^! ~& m2 S! m# `9 o: D---- 用CreateDIBitmap()创建显示用位图,用CreateCompatibleDC()创建兼容 & h( d9 B% r/ d; ?7 F( L; x- ~' g
DC,
) T: ]8 \: ] F+ H
9 ^% p+ A' p/ o0 p0 ]---- 用SelectBitmap()选择显示位图。 $ k. n6 ~0 X. o5 ~1 r
1 o# o V. H2 N% O
---- 4. 用BitBlt或StretchBlt等函数显示位图 r7 p% Z9 P) } \: T5 K$ Z
; ?, x9 J# z/ Y( Y! f+ I- A+ U
---- 5. 用DeleteObject()删除所创建的位图
7 h8 _1 z- [& E ( q/ j" ~' v7 J) |! E/ j: e1 T& Z
---- 以上方法的缺点是: 1)显示速度慢; 2) 内存占用大; 3) 位图在缩小显示
) q' v5 c1 h% B; c' A1 j; C! l时图形失真大,(可通过安装字体平滑软件来解决); 4) 在低颜色位数的设备上(
* l+ l7 M: \& U如256显示模式)显示高颜色位数的图形(如真彩色)图形失真严重。 # T' @; k" Z$ o3 R9 w3 G
' _4 F& w! x2 a$ {
---- 三、BMP位图缩放显示
' | G* H5 K# S& K1 S! Z
( h4 @/ X. o B4 _% c( E---- 用DrawDib视频函数来显示位图,内存占用少,速度快,而且还可以对图形
: }" h( ^# l! V, p8 ]- \进行淡化(Dithering)处理。淡化处理是一种图形算法,可以用来在一个支持比
$ v t7 a+ i* Q. ]- A: H图像所用颜色要少的设备上显示彩色图像。BMP位图显示方法如下: , B' ?8 T% A) O3 K
: Q& ~: @4 `# B---- 1. 打开视频函数DrawDibOpen(),一般放在在构造函数中 4 E4 C0 e7 U3 \/ f
% A, z# \ p+ Z
---- 2. 申请内存空间用于存放位图文件 $ u3 t' Z. D. z# h/ V. C/ P, g
$ j9 Q- P \6 {0 B6 J+ o {---- GlobalAlloc(GHND,FileLength); # F5 t5 K1 [. P( C: H$ H
% o% N [3 j# R% d( w---- 3. 位图文件读入所申请内存空间中
: v# W! `9 u! J. q( e. t5 d
% V( x7 j: Y* e9 |---- LoadFileToMemory( mpBitsSrc,mFileName);
1 M" [. T5 j% i2 m1 B3 ?
+ P7 M$ x' N4 }: b---- 4. 在OnPaint等函数中用DrawDibRealize(),DrawDibDraw()显示位图 5 B; ?5 D% g X9 `' O; V3 ^; q& B
; l* |9 _: {8 g2 W* e; `
---- 5. 关闭视频函数DrawDibClose(),一般放在在析构函数中
( O' d+ x6 \1 o7 t ) B9 C+ s" g, \. g. Y4 v& T7 U
---- 以上方法的优点是: 1)显示速度快; 2) 内存占用少; 3) 缩放显示时图形 - F7 |4 E0 r) j" q4 R0 q" j7 v
失真小,4) 在低颜色位数的设备上显示高颜色位数的图形图形时失真小; 5) 通
# f3 S2 F8 w- j$ s$ R1 a2 r. ]2 _过直接处理位图数据,可以制作简单动画。 3 v* K' h$ k. H1 V4 A) T: M
* c9 a/ g9 ?. O' D5 L/ C---- 四、CViewBimap类编程要点
5 ]0 |- P$ B1 }: H5 y' d 0 c) C3 w' x% k2 X6 E" k
---- 1. 在CViewBimap类中添加视频函数等成员 4 V" [) p3 z8 e4 m8 J
7 Z; B3 _0 G: @% {' n4 T/ |. s' eHDRAWDIB m_hDrawDib; // 视频函数
0 [) P( e& L" |, X+ S) n; cHANDLEmhBitsSrc; // 位图文件句柄(内存)
# U# k) c8 x7 @; v7 b7 z5 ALPSTR mpBitsSrc; // 位图文件地址(内存) $ D8 b. C% v; |' D: |
BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头
4 Y# I8 [0 g' |4 {+ f + {4 n8 M6 A) y0 L) S5 k' C
* Z: ~6 W- l$ k0 h0 s! B0 w3 G* v# P3 `) @---- 2. 在CViewBimap类构造函数中添加打开视频函数 4 t j* ]3 m7 j. L, _) B( }) Q: I4 `
---- m_hDrawDib= DrawDibOpen(); 9 E, W6 p7 b3 x# B
6 p9 u7 M0 P+ B
---- 3. 在CViewBimap类析构函数中添加关闭视频函数
. k7 d Z& p. s- ~2 V% \' S- U8 B3 | 1 d/ B) p0 D1 J) o8 b4 d0 s
if( m_hDrawDib != NULL) G4 c* M5 G9 W* R5 Q% m- m3 _" t5 B
{
; ?5 L6 F; i- }: F" Q/ ^; q DrawDibClose( m_hDrawDib); & p& Q1 D4 ~3 | p* M( \9 L( t6 P
m_hDrawDib = NULL;
8 o' o9 p, X0 O' [0 o, N } ; O3 b. W7 M% L. G f E5 I
) n# ]) R& R! A/ i1 t0 o' O8 [ 1 Y% }. M2 }0 X6 R
---- 4. 在CViewBimap类图形显示函数OnPaint中添加GraphicDraw()
) N4 T, |: u* E* _# A5 jvoidCViewBitmap::OnPaint() ! M% i) q, ?' }. U- l& N
{ 7 w1 \- |( U$ J
CPaintDC dc(this); // device context for painting
1 t% S- @* [1 H2 D$ m* }8 \0 |) YGraphicDraw( ); * o* i' d4 p& r5 G& G9 }& A
}
! ~8 k: x) X& G+ ] * A6 X/ D' }$ p' a% g
voidCViewBitmap::GraphicDraw( void )
) K4 x4 c8 m l{ ) u4 S: ^7 \9 P0 M/ {. c( Q0 `/ f
CClientDC dc(this); // device context for painting ) ]% X6 G- o# a' G# r
BITMAPFILEHEADER *pBitmapFileHeader;
1 q* ~" }/ G, {0 X' `ULONG bfoffBits= 0; 6 ~5 Y0 ^' H( o, `3 }
CPoint Wid;
9 {- j. n! Z0 \
& p! Z S' }# E) D! N/ y// 图形文件名有效 (=0 BMP) / a) J/ g& f& `8 D, _$ r% D
if( mBitmapFileType < ID_BITMAP_BMP ) return; 2 w* S- s, }. u" q4 J( x7 ?) F5 \
! H5 B0 a, d9 H$ j7 ~
// 图形文件名有效 (=0 BMP)
' z7 h, p9 N1 n! x0 [4 T: y6 e! H// 准备显示真彩位图 - Y6 Q5 G2 c/ w6 Z
pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc; # M, s3 M9 T; {" ?7 G7 |
bfoffBits= pBitmapFileHeader->bfOffBits;
( }; e3 `- H% U# s! v 0 c) p7 c( n4 U# _- @# a+ U
// 使用普通函数显示位图
( C U! z5 W' v7 o " @+ w. E2 J" D7 z; a8 e
if( m_hDrawDib == NULL || mDispMethod == 0)
$ }# i/ P5 [2 {' } {
7 x& G, ^& }( G1 o HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,
/ }' I( n( y" c( D2 smpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits, 6 d( K5 ?) t" {% e- {
(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);
" O; r/ K7 s7 `// 建立位图
8 F4 n0 Y( b( \- i ?7 p3 h P7 vHDC hMemDC=::CreateCompatibleDC(dc.m_hDC);// 建立内存 4 N8 j6 x4 q# s( x& N% v5 G; | z
HBITMAP hBitmapOld= SelectBitmap(hMemDC, hBitmap); // 选择对象 0 o$ w( i0 }6 T( C# Z' f5 k4 w$ a
// 成员CRect mDispR用于指示图形显示区域的大小. 3 p9 d; \) L P2 t( y1 O
// 成员CPoint mPos用于指示图形显示起始位置坐标. 8 F; k! u& A5 R/ Z
if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() ))
4 B5 N3 U# q% D3 [6 kmPos.x= mpBitmapInfo->biWidth - mDispR.Width() ; ( W" ^0 o# N/ h% i
if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height())) 3 {3 X8 k6 @5 E
mPos.y= mpBitmapInfo- >biHeight- mDispR.Height(); 9 _6 z2 I; A1 ]. @4 L8 w8 L
if( mPos.x < 0 ) mPos.x= 0;
0 {7 W5 j7 \8 J- x" V: p# N if( mPos.y < 0 ) mPos.y= 0;
2 j" y0 w: e, C : g$ g: P$ ~. ^# b( S
if( mFullViewTog == 0) . j, A1 Z3 R$ P( q; E' v: z4 t6 Y
{ 4 x' @" e# d" |1 A, o
// 显示真彩位图 7 V: d& A2 _5 J9 c- x9 u, b
::BitBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(), 9 R' L3 Q2 m0 w1 [: }
hMemDC,mPos.x,mPos.y, SRCCOPY); - ]" V" J" F9 m X
} else { ; u# R. [3 V+ i- Q5 Y
::StretchBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(), ' H$ \0 ~/ L4 `3 z- W% p: d4 H
hMemDC,0,0, mpBitmapInfo- >biWidth, mpBitmapInfo- ) ] z5 c1 c6 g) F6 i- p
>biHeight, SRCCOPY); * h$ M3 G) r" j% U
} 9 H9 u7 {! A. _; ?* n6 F Q
// 结束显示真彩位图
, n& t) Q+ Q* I3 R/ v : eleteObject(SelectObject(hMemDC,hBitmapOld));
6 e; `2 p7 x/ t// 删 除 位 图 , R; Z( M& P8 k ?7 g& L
} else {
5 \) d( \! x7 T; G2 ?! C+ ^
2 c0 ^ r- W# Z5 H, @ // 使用视频函数显示位图 , U+ X: E$ i7 z5 i7 V
- W0 p9 j6 A% Q! X
if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() )) 7 m8 b: N, T0 ]7 [+ r0 s5 i5 ]6 @
mPos.x= mpBitmapInfo- >biWidth - mDispR.Width() ; + |& A7 i, z2 g5 Z
if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height())) ) ^- A" n8 N0 B; a& S7 r: J0 g
mPos.y= mpBitmapInfo- >biHeight- mDispR.Height(); % V& o, r7 Q% J1 a9 g4 L `
if( mPos.x < 0 ) mPos.x= 0;
! }9 ?8 K5 r; g/ J& b% q if( mPos.y < 0 ) mPos.y= 0; g4 o2 U# E0 N' F% A) g7 o- {. E
- ?' q8 k& q& w6 a3 ` // 显示真彩位图 . X" n2 O( f& g3 U x \; b
DrawDibRealize( m_hDrawDib, dc.GetSafeHdc(), TRUE); / g5 V# D4 o) L# w+ T2 e
" o3 L& a" m0 d9 n% H if( mFullViewTog == 0)
) {8 r$ @3 T* k1 U' P{ 1 I" B# f: b! p& p* d
Wid.x= mDispR.Width(); - M. r- b! o c2 r/ j. c/ E, l7 v
Wid.y= mDispR.Height(); # P, ^# W/ T6 D) Q
// 1:1 显示时, 不能大于图形大小 B; S. a- F* ?
if( Wid.x > mpBitmapInfo- >biWidth ) 7 l& g* x2 f8 L$ t& o% q' o* L
Wid.x = mpBitmapInfo- >biWidth;
7 ^3 {8 E8 Y" s# v0 G, yif( Wid.y > mpBitmapInfo- >biHeight)
" ~* |: L# z9 c2 m2 d6 WWid.y = mpBitmapInfo- >biHeight; 8 t' n3 G3 I) ]$ g6 R Z# u& J) |
4 ?7 Q' k* V s( j% y7 ~; L5 o9 T
DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()
& ^+ V: Y0 p4 ^- _/ i, 0, 0, Wid.x, Wid.y, & S0 w `, I. ^# e' n
mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),
3 f' B+ A( |# a3 C& BmPos.x, mPos.y, Wid.x, Wid.y, DDF_BACKGROUNDPAL); ( w. s6 ?* u9 D' m2 ?8 ~; _3 C) G
} else {
8 w3 J, k* W8 J7 k" [- _DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),
4 K: B0 z5 v8 T2 I! G0, 0, mDispR.Width(), mDispR.Height(),
( l" T" S# c0 w4 empBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),
2 e7 w7 w# e- t1 l4 p0, 0, mpBitmapInfo- >biWidth, mpBitmapInfo- >biHeight,
' ?& z7 |% k9 l% L* HDDF_BACKGROUNDPAL); " K3 K ], r/ U+ x6 h# @( ~( I
}
) W* z6 g: ^3 R2 t) `9 [ } 3 D/ p5 N, P; t
return; $ K6 q" _ r5 { j# D A
}
" }* v2 k4 F, Y8 I& w/ O 6 g2 ?& h1 @. @' e5 P( c
1 @# j# A O p) w2 h+ j2 Y x {& n
---- 五、使用CViewBimap类显示BMP位图
# R7 G, E* W! Q4 B0 Y---- 1. 在Visual C++5.0中新建一个名称为mymap工程文件,类型为MFC : t+ c6 @3 g8 G
AppWizard[exe]。在编译运行通过后,在WorkSpace(如被关闭,用Alt_0打开)点 ' C( ?' Y4 |- F' U+ A. b
击ResourceView,点击Menu左侧的+符号展开Menu条目,双击IDR_MAINFRAME条目 0 D$ I6 s+ Z9 L8 h/ ]' t. w
,进入菜单资源编辑,在'“查看(V)”下拉式菜单(英文版为View下拉式菜单)的 + }7 L8 [; }6 O, m r, |
尾部添加“ViewBitmap”条目,其ID为ID_VIEW_BITMAP。
( ^5 l# K; D7 y4 w2 }; V' a
5 |6 I2 A9 l2 L---- 2. 在Visual C++5.0中点击下拉式菜单Project- >Add To project-
) E$ x5 H, @; f6 {>Files...,将Bitmap0.h和Bitmap0.cpp添加到工程文件中。 % i$ m8 K% q) p# P% ~& O
% p' {, P9 j1 Y- e---- 3. 在Visual C++5.0中按Ctrl_W进入MFC ClassWizard,选择类名称为
4 K$ W5 Y# Y( C. @' D& z3 S7 } tCMainFrame,ObjectIDs: ID_VIEW_BITMAP,Messages选择Command,然后点击Add * X3 s6 Y* g. \: i- H& B1 A
Fucction按钮,然后输入函数名为OnViewBimap。在添加OnViewBimap后,在 ! j3 _2 R1 |4 R2 D1 D& h/ x h
Member functions: 中点击OnViewBimap条目,点击Edit Code按钮编辑程序代码
4 o1 N' b, G# |+ r: Z. u。代码如下:
1 f8 ]/ w" q/ p8 e# a
, p( P* q7 h. o/ h& F5 Pvoid CMainFrame::OnViewBitmap()
& r/ u$ P+ B2 [+ S$ |$ l{
$ D0 ?4 L' w& @, k// TOD Add your command handler code here
) N/ K8 ~4 _: ^% f! z4 ACViewBitmap *pViewBitmap= NULL;
" p4 E$ f- W }1 I0 N- A 8 n. d6 Z7 b. U; p* ~* u
pViewBitmap= new CViewBitmap( "BITMAP.BMP", this);
' O' _$ }0 n( _4 O$ {* [% i& Z& fpViewBitmap- >ShowWindow( TRUE);
# W! f. t% _; j9 B0 W} & t( s1 o: `$ c
% A0 I8 t- T+ V! l# ?& c
0 v9 t& K9 R J/ D( g. T8 `---- 并在该程序的头部添加#include "bitmap0.h",然后编译运行。 & D8 G7 s6 J5 c
---- 4. 找一个大一点的真彩色的BMP位图,将它拷贝到BITMAP.BMP中。
. n" N% U) B+ x. x. t& }5 g) ]! e5 i 8 \0 M, G- x; a0 e9 L0 G! n
---- 5. 运行时,点击下拉式菜单“查看(V)- >ViewBitmap”(英文版为View- >
. g. R$ M; D$ `2 T0 c( L ViewBitmap)即可显示BITMAP.BMP位图。 2 z9 x X6 N! U' p2 h
; ^8 z# w: b! n, ?. D+ R3 g/ a# }---- 六、CViewBimap类功能说明 0 ?, ~- F2 h4 k4 l( ]1 {
5 W' p( w% {5 B) G( K t
---- 1. 在客户区中带有水平和垂直滚动条。在位图大小大于显示客户区时,可
1 A' a2 G2 w, d( m以使用滚动条;在位图大小小于显示客户区或全屏显示时,滚动条无效。
, I0 a4 K7 J2 X: k( S" t
9 {, w% J# w) F0 A2 P---- 2. 在客户区中底部带有状态条。状态条中的第一格为位图信息,第二格为 - H$ j R' I# v/ o7 {' g/ W
位图显示方法,可以是使用普通函数或使用视频函数。在第二格区域内点击鼠标 ! a2 w% l8 X7 }: Y) T6 h, c. Y
,可在两者之间接换。第三格为位图显示比例,可以是1;1显示或全屏显示。在
! `- R x, W& o: C* }! p* L- c第三格区域内点击鼠标,可在两者之间接换。在全屏显示时,如果位图比客户区 2 d1 ~3 I' Y3 [
小,则对位图放大; 如果位图比客户区大,则对位图缩小。
7 |0 f4 Z- s6 ]+ c ! B% Y0 D& I* ]# t* A
---- 3. 支持文件拖放功能。可以从资源管理器中拖动一个位图文件到客户区, - g) f* W0 U! S7 ~9 t9 u) T
就可以显示该位图。 $ D' m! Q1 O" F5 M8 S# v$ f- e
1 h$ A, S* u' U$ b1 y2 C& i/ S
---- 程序调试通过后,可以找一个较大的真彩色位图或调整客户区比位图小,
_# } b6 o2 m+ q( r/ l0 z6 E2 W# g4 i7 _
在全屏显示方式下,比较使用普通函数与使用视频函数的差别。可以看出,位图
: D; P* c5 Q, S7 p放大时两者差别不大,但在位图缩小时,两者差别明显; 使用视频函数时位图失
1 ~3 A `$ q3 [. F+ a真小,显示速度快。 , l8 `) _6 C3 j( k. `. _' ?
( V# C1 e* w# K9 ^
---- 还可以从控制面板中将屏幕显示方式从真彩色显示模式切换到256色显示模 ' W4 T1 g. u# i; t2 O |7 _
式,再比较使用普通函数与使用视频函数显示同一个真彩色位图的差别。现在可 9 h8 V+ ?. \3 a9 k/ R* ^
以体会到使用视频函数的优越性了吧。 1 @. |4 p) {2 _$ N6 ~! O* \. l
; j5 n L4 p' i. l6 \4 g---- 在全屏显示时,位图的xy方向比例不相同,如要保持相同比例,可在显示
2 F0 j( p, t ~& u5 A$ R' E7 t* g% C程序中加以适当调整即可,读者可自行完成。 |