|
5 E D$ p! T6 M5 _, T2 W- d
西安交通大学流体机械研究所
, U' q) l1 Q" Q" z |1 q% D张义云
8 {8 o+ p1 n S3 n, v5 |
3 I. N+ o- t* ^- J. U2 V; A% t+ B% @---- 用普通方法显示BMP位图,占内存大,速度慢,在图形缩小时,失真严重,
0 Q2 T, e; v0 O q在低颜色位数的设备上显示高颜色位数的图形图形时失真大。本文采用视频函数
$ X' r7 |) Q6 H$ }" M$ d显示BMP位图,可以消除以上的缺点。 ' @3 o2 r Y: {3 {9 |7 j0 }
3 H+ C% [! i# `/ H---- 一、BMP文件结构
! u' \3 @3 L: H2 f4 E4 J* Q
( J D: P* |, v8 s' k" g0 ]---- 1. BMP文件组成 8 b9 h7 d9 a* C6 E: d
$ X0 ~9 K$ q+ q. J( _; q
---- BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。 $ o& u6 ]% m- k0 P3 a+ g) Z+ j0 D
) r+ T- F' O$ p4 _
---- 2. BMP文件头 4 A. q/ s. |3 P/ l; z
, M6 V V! F% E* R9 l- ~# w2 P* P
---- BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息
* f* `4 @ f4 `* m9 P' ^。
g8 k$ u3 K: A" ^7 l
5 ~0 T6 ^& w7 ^---- 其结构定义如下: ( i' g# l# F j
. Q% K/ K7 W' c$ B1 P# ptypedef struct tagBITMAPFILEHEADER
7 E% x* e! g. p: Y- D0 r5 _: ^. ^{
4 q: O' D) N5 B! G0 F/ DWORDbfType; // 位图文件的类型,必须为BM
( _) K& U) N2 M/ F' ?DWORD bfSize; // 位图文件的大小,以字节为单位
) ~ T' K; e) x( G8 q) u: G% R% ^WORDbfReserved1; // 位图文件保留字,必须为0 }" Z+ t4 G2 `+ ]. N4 N
WORDbfReserved2; // 位图文件保留字,必须为0 9 r4 q3 h8 K% @) ?
DWORD bfOffBits; // 位图数据的起始位置,以相对于位图 4 H2 n: @ T. g) K' V! m
// 文件头的偏移量表示,以字节为单位 P9 S: i; p J; E6 e& g! \
} BITMAPFILEHEADER; 0 l( D: t3 g- i$ k% I
0 o$ j9 L/ L* E( V4 [9 }# Q
$ [9 Z1 p" B4 n0 b: v+ _---- 3. 位图信息头 & _- ]7 q- u) G" {+ p
---- - _2 w0 d+ t# T Z2 G
1 v# J& F0 ]- r# J# H$ d2 j; PBMP位图信息头数据用于说明位图的尺寸等信息。 * O# C7 w3 o' _/ U- h
typedef struct tagBITMAPINFOHEADER{ . k+ T; V. J- W B X
DWORD biSize; // 本结构所占用字节数
; c" p; f( D4 k7 x LONGbiWidth; // 位图的宽度,以像素为单位 5 s* k% p5 _$ D7 Z# E2 G
LONGbiHeight; // 位图的高度,以像素为单位
k+ _5 [7 }$ Z9 u4 p7 \4 i9 m WORD biPlanes; // 目标设备的级别,必须为1
8 y) ?. Q2 M; x4 m7 u7 ]) l: z3 K WORD biBitCount// 每个像素所需的位数,必须是1(双色),
, y" Q( j* @9 x" y% Q // 4(16色),8(256色)或24(真彩色)之一 * s p* ?) t3 B, q
DWORD biCompression; // 位图压缩类型,必须是 0(不压缩), . Z* t x( @# X7 `' a: e
// 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一 $ v+ M' c( K u
DWORD biSizeImage; // 位图的大小,以字节为单位 7 o7 G* m% M3 z# l9 O
LONGbiXPelsPerMeter; // 位图水平分辨率,每米像素数
' Y& T Z3 q3 x: o. e" _; N LONGbiYPelsPerMeter; // 位图垂直分辨率,每米像素数
( H r. P4 |5 O+ t0 H( Q DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数 # X9 a4 H: J" I! W
DWORD biClrImportant;// 位图显示过程中重要的颜色数
! D$ J% n) F6 G- ]} BITMAPINFOHEADER; $ Y n1 ^; x9 I& z( p/ M
% p+ b( D& v7 T/ W; l+ M; s" N, c
5 S, r4 g, ]) M R+ N" k---- 4. 颜色表 ' m' C& B' Q/ p$ J' _
---- 颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个
8 O4 a' i- S4 pRGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下: ' Z+ `: Q3 n5 o) _6 l' ^
+ Q% \3 K8 G/ _! M
typedef struct tagRGBQUAD {
7 l% D2 E+ k/ _9 j/ C0 ? k+ H7 PBYTErgbBlue;// 蓝色的亮度(值范围为0-255) . y( Q6 M" J- ?
BYTErgbGreen; // 绿色的亮度(值范围为0-255)
2 m) z& H& Y6 g9 c- tBYTErgbRed; // 红色的亮度(值范围为0-255) 8 g! T8 E3 R H' G& i
BYTErgbReserved;// 保留,必须为0
) a" q3 U* B# p, a0 N7 n} RGBQUAD; 2 R* Y/ ?; D6 V
颜色表中RGBQUAD结构数据的个数有biBitCount来确定:
0 S/ |1 V/ O# s7 g& c, @当biBitCount=1,4,8时,分别有2,16,256个表项;
: }. n( P1 {. k8 m当biBitCount=24时,没有颜色表项。 1 q* k% a( O* N- L+ J
位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:
* x2 M+ A C8 Q J T L# Z& Dtypedef struct tagBITMAPINFO {
. y1 |+ e! Y3 T( I9 v f BITMAPINFOHEADER bmiHeader; // 位图信息头
8 t! \/ |. ~$ V, `3 l- u RGBQUAD bmiColors[1]; // 颜色表
$ R' O3 e/ }0 M3 u" H. m s} BITMAPINFO; ) e# B6 m( x7 y V
. G$ I. I7 W3 v' f; q( Z u
6 a& K$ ] m; T$ p- v5 g6 y
) w8 Q4 A' \$ q" ?* I4 s8 Y6 n---- 5. 位图数据 * F( o% V8 ^& @% k3 R9 _" d7 ?
---- 位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右 - Z& I& _2 b2 @/ O8 y7 a6 X
,扫描行之间是从下到上。位图的一个像素值所占的字节数:
* _# q, f$ _; [5 D+ A
9 |" A6 h7 \0 O5 O9 \. e B当biBitCount=1时,8个像素占1个字节; 9 C) P8 Z' P3 J I7 B2 h3 Q: S' [: e
当biBitCount=4时,2个像素占1个字节; 8 `7 S8 S( {4 w2 |+ f! O
当biBitCount=8时,1个像素占1个字节;
; e; L/ X+ m7 V当biBitCount=24时,1个像素占3个字节;
" w+ @4 u. h# `2 A- _Windows规定一个扫描行所占的字节数必须是 * l) ]0 @* Z2 J' `6 y* k5 o
4的倍数(即以long为单位),不足的以0填充,
2 |1 {$ v9 @& R S* e/ s一个扫描行所占的字节数计算方法: . {+ P) l' m5 V2 K- E0 i
DataSizePerLine= (biWidth* biBitCount+31)/8; , f1 C% D6 w# q0 }: {
// 一个扫描行所占的字节数 " B0 k% ]0 W. _. V5 {1 n
DataSizePerLine= DataSizePerLine/4*4; // 字节数必须是4的倍数 ; }) A# {" A- [! o
位图数据的大小(不压缩情况下):
5 J, [: ~1 o+ v4 ~3 ?% b+ fDataSize= DataSizePerLine* biHeight;
& K# [5 i! S$ U9 g) {; D
$ e# T. J a) e- j2 z8 O
+ G% c) C! M9 z* _- h---- 二、BMP位图一般显示方法
$ ^! ?- R v }/ V4 L---- 1. 申请内存空间用于存放位图文件 7 U! D' Y- ~# a1 p! J. Z
, Z7 @% F9 x# Y }---- GlobalAlloc(GHND,FileLength);
9 k1 K$ I* A: U9 g* ^& Z " u( @+ C* l* Y% Q; C; Y* ^
---- 2. 位图文件读入所申请内存空间中 / Y+ u0 C8 ?6 i x; {
& Z$ F& w3 u- b" F% N---- LoadFileToMemory( mpBitsSrc,mFileName);
1 C( R. E( Y1 U; ]7 o! [" f
- b/ a* D& ^8 [: ?% k3 u! Y, y( A---- 3. 在OnPaint等函数中用创建显示用位图
' V- z* m. n, t2 x" Q: L
: b; L. I: D6 @0 d---- 用CreateDIBitmap()创建显示用位图,用CreateCompatibleDC()创建兼容 : `% O: d4 q, N I
DC, * Q Y# Q4 C4 G! z$ V& C
: f) c. {% z" f& L. @
---- 用SelectBitmap()选择显示位图。 9 x2 _( N, b$ ]! c o% m- `
$ l; Z- m; k' x3 M# o% L* H
---- 4. 用BitBlt或StretchBlt等函数显示位图
/ \. k- m% y) s1 c / E$ R# [ |2 u y! C8 c5 e
---- 5. 用DeleteObject()删除所创建的位图 9 h1 P4 M) ]6 o. I: s8 d$ o
$ t) u# f; L& u) w
---- 以上方法的缺点是: 1)显示速度慢; 2) 内存占用大; 3) 位图在缩小显示 5 Z2 p5 e7 k. y0 z2 l9 X
时图形失真大,(可通过安装字体平滑软件来解决); 4) 在低颜色位数的设备上(
4 g+ ?% f! F- t8 `7 y6 }如256显示模式)显示高颜色位数的图形(如真彩色)图形失真严重。 " L- g- p$ Q2 |
( \- }+ v( S' a: V2 n v
---- 三、BMP位图缩放显示 ' H) F6 x( _- u) D3 d+ x1 u; W
/ Q9 i) e1 K( A5 |
---- 用DrawDib视频函数来显示位图,内存占用少,速度快,而且还可以对图形
( [6 ^# t+ y# I! |- M& @5 w进行淡化(Dithering)处理。淡化处理是一种图形算法,可以用来在一个支持比
, b+ M, L* R) O, e& R5 Y1 P1 l图像所用颜色要少的设备上显示彩色图像。BMP位图显示方法如下: * _4 i8 N- V d# P! g6 C) a
, p$ _2 A& r+ H---- 1. 打开视频函数DrawDibOpen(),一般放在在构造函数中 . B4 {( E5 X. M# ?; `: k i
3 H$ A7 D3 n' O---- 2. 申请内存空间用于存放位图文件
/ a% Y* l; X0 Q! U0 W8 ~! ?' I( U! [ / f, y' h# U) R* F! V2 ~
---- GlobalAlloc(GHND,FileLength);
7 L' H: A) c$ R) _& n, Z2 m; X
3 w. }' }/ u/ u! S- w l \0 t; u/ f---- 3. 位图文件读入所申请内存空间中 ) M- s& F+ {5 H6 |1 e
4 h3 ~/ J8 b: G# `( K8 z6 ~---- LoadFileToMemory( mpBitsSrc,mFileName);
# o; [ F/ M8 z) G4 F1 S, r+ Z# M
* [* s9 |, v) `+ V---- 4. 在OnPaint等函数中用DrawDibRealize(),DrawDibDraw()显示位图 5 M, z2 S7 f" p
$ A$ H: c. v. l; [8 m; g
---- 5. 关闭视频函数DrawDibClose(),一般放在在析构函数中 5 m& \1 |* }" d, L( G
. S+ n* a A. N& S% [# }---- 以上方法的优点是: 1)显示速度快; 2) 内存占用少; 3) 缩放显示时图形
7 ~4 V! s' K/ V g# g6 [' W失真小,4) 在低颜色位数的设备上显示高颜色位数的图形图形时失真小; 5) 通 - ^( r( @- F% Y2 l3 b' T
过直接处理位图数据,可以制作简单动画。
; I8 q# ` B0 A5 q ! N! l; J6 c5 E2 m/ ]
---- 四、CViewBimap类编程要点 9 @9 ?+ n. `) n& b2 v7 @
" f4 b' m X* j0 H; M! D/ P
---- 1. 在CViewBimap类中添加视频函数等成员 1 k6 s$ t. L w. j0 u3 Q6 S5 w5 W2 A
# {5 r0 U+ A( }+ v+ P4 a1 S% p
HDRAWDIB m_hDrawDib; // 视频函数
4 i5 \ J+ ]( [# XHANDLEmhBitsSrc; // 位图文件句柄(内存) 3 Y2 y, @* J8 `* X: Z& Y' j
LPSTR mpBitsSrc; // 位图文件地址(内存)
8 f) S) b# c: W8 A* r8 ZBITMAPINFOHEADER *mpBitmapInfo; // 位图信息头 # _" K% m: D; y _: M' U9 u1 E
* M) H% q5 f5 L% y% y
" x/ t' j' y7 m( E7 E
---- 2. 在CViewBimap类构造函数中添加打开视频函数 , O' U i$ f1 k5 f7 g p
---- m_hDrawDib= DrawDibOpen(); 2 g' Z5 Q/ C& i h* l
: b& Q, B! F& i& r) @+ J/ T
---- 3. 在CViewBimap类析构函数中添加关闭视频函数
9 G/ u. Z6 c( F$ O; w
2 C( I2 Q. m F# uif( m_hDrawDib != NULL)
$ \+ l$ q& [: M+ Q5 ~/ `: R. S { 5 R0 H$ y0 ?& X5 U% m* W$ p( p
DrawDibClose( m_hDrawDib);
) L: `. ?/ S5 H* t m_hDrawDib = NULL; + M) G# u0 j5 m
} " c, ?$ Z; m4 E9 J, g& T* Q) {
/ d$ y$ j2 C2 \" W
- J1 c! l# ^- l2 J0 t. x; T---- 4. 在CViewBimap类图形显示函数OnPaint中添加GraphicDraw() 4 D( O+ E- w' D
voidCViewBitmap::OnPaint() ! ]- ` A( K! f) l
{ ! t+ U7 \* d5 ?# c/ x
CPaintDC dc(this); // device context for painting 6 z' h" q5 ]# n: ]
GraphicDraw( );
! i$ _ k2 l2 |3 \9 S& m} : b: y- m. X* ^. G, \
; i5 N R! M, c K& h* ]; _# C( f7 ?voidCViewBitmap::GraphicDraw( void )
) P. n! n5 d. k" c! a: e' O- A{
& H m9 C; S2 _* @5 N) ?CClientDC dc(this); // device context for painting % q0 t/ A5 n) F# O- A- a
BITMAPFILEHEADER *pBitmapFileHeader; % v# W6 Z2 k7 K' Y
ULONG bfoffBits= 0;
$ ]1 f* \8 `# m) W7 L* [CPoint Wid; 4 \1 J: @ q! h) j1 `8 V1 {* X
% C" |" V8 \7 K// 图形文件名有效 (=0 BMP) - M, q# k& g$ `5 Q) v
if( mBitmapFileType < ID_BITMAP_BMP ) return;
+ \/ a: E% I; c& ]% `* H' M. S + ]9 H0 [5 r3 ?; ~, R3 R
// 图形文件名有效 (=0 BMP)
9 G4 o- n, E% g// 准备显示真彩位图 5 Z1 Z" j: z: {# y& C! f% g, }
pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc; 2 Z7 l: i+ R c+ H0 L2 C
bfoffBits= pBitmapFileHeader->bfOffBits; , i6 K& ?$ x9 Q
* u# Q3 e" A5 L( H// 使用普通函数显示位图 6 P7 g; X) U, M0 A
0 S( `0 s* j$ w, f+ j5 H) D
if( m_hDrawDib == NULL || mDispMethod == 0)
' [! O M, Y0 A5 h7 c' t+ ^ \ { . ^' ? M2 i4 K) W) N3 h
HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,
; R: y& t) ]/ z% e( D2 F9 P0 rmpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,
+ r* i5 A. S# D# }" M5 X (LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);
; g7 X2 S7 M; V# V// 建立位图 ' }* h8 G' O. o
HDC hMemDC=::CreateCompatibleDC(dc.m_hDC);// 建立内存
, ?, w. f$ D0 ]- cHBITMAP hBitmapOld= SelectBitmap(hMemDC, hBitmap); // 选择对象 0 l9 y; Z' z; A6 r5 q u" _
// 成员CRect mDispR用于指示图形显示区域的大小.
. v7 E8 ?, b/ U. S// 成员CPoint mPos用于指示图形显示起始位置坐标.
5 X* G3 B1 F* Vif( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() ))
' H' f" S1 t3 f7 h+ ~" C! y- @/ pmPos.x= mpBitmapInfo->biWidth - mDispR.Width() ;
/ q2 G" t9 r* g* ? if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height()))
/ V E/ Z/ F/ c& g: a/ B/ n8 `9 |mPos.y= mpBitmapInfo- >biHeight- mDispR.Height();
( B( A; s0 w* F& m8 t9 { U0 ~ if( mPos.x < 0 ) mPos.x= 0; + e6 H& j* U; w
if( mPos.y < 0 ) mPos.y= 0; : r% z! n) |6 _* M
$ ]8 g8 O: B2 l/ E( c2 p3 m7 D
if( mFullViewTog == 0) ! \* n j" N4 {$ O X; K: ]
{ ' c; g1 [8 X9 S8 V) V$ D: _9 m# g
// 显示真彩位图
) X) r: y* v( j5 `6 }6 s2 l3 p6 ]- t::BitBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(), # i# y7 E: Z2 i6 A7 q& A
hMemDC,mPos.x,mPos.y, SRCCOPY);
% J$ r* ]5 Y8 T, Q1 H" V} else {
, B" K" X g7 b" T; ?1 {::StretchBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(), * T ]( h4 m! S: b
hMemDC,0,0, mpBitmapInfo- >biWidth, mpBitmapInfo-
* o# F0 n) \# l4 \>biHeight, SRCCOPY);
" m8 s7 n" Y9 w2 M9 ]& h0 Z/ O} 9 U% O9 k* q9 N9 ], \ O
// 结束显示真彩位图 # \8 r" _2 ^5 ^
: eleteObject(SelectObject(hMemDC,hBitmapOld)); " @1 m* ~6 F% ]
// 删 除 位 图
7 d6 {& f/ a# J' Q9 l2 X } else { * U* G( x5 b7 b
5 u1 G; M& b2 H% w' V
// 使用视频函数显示位图
% h5 W( J O6 b0 Z 3 E" q% ?. D* Z1 V' W6 k
if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() )) + x& a+ h8 b( U4 q& s+ I; i; G# Q
mPos.x= mpBitmapInfo- >biWidth - mDispR.Width() ;
$ B3 b4 C! U4 I8 Q Q) Q$ u4 Y if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height())) , s& {' ?( l6 b: ^& O+ f2 d
mPos.y= mpBitmapInfo- >biHeight- mDispR.Height(); 1 x, f' P: Q9 c( `7 M' U2 \- L6 p( Y
if( mPos.x < 0 ) mPos.x= 0; ' f7 J5 Z: c% b9 H3 v! X+ i! d
if( mPos.y < 0 ) mPos.y= 0;
' k w8 Z; ^* l7 _+ a% e . L8 d+ R- ]) _: ~
// 显示真彩位图
( Q! h3 n# A4 Z0 D* O DrawDibRealize( m_hDrawDib, dc.GetSafeHdc(), TRUE);
. b& w! a. J7 W- q3 H2 O3 b : Z$ m; v# Z! }3 L
if( mFullViewTog == 0) 1 z0 n6 ^8 N8 _0 r- w
{ w7 i1 t% L* N1 L+ V
Wid.x= mDispR.Width();
5 v/ E8 {, q7 V9 z0 V7 BWid.y= mDispR.Height(); , B$ w# J8 l/ p" F; h3 C+ X3 E
// 1:1 显示时, 不能大于图形大小
2 Y* w, v" t9 c; ?% d* F: hif( Wid.x > mpBitmapInfo- >biWidth )
; O5 l! H* M' f2 T5 f( A6 D2 IWid.x = mpBitmapInfo- >biWidth;
- D# l6 I' h- N( m; r/ Q/ Dif( Wid.y > mpBitmapInfo- >biHeight) & R: w" b% i% R
Wid.y = mpBitmapInfo- >biHeight;
3 N0 ?! L% q: k4 L
- {0 N( B) p# s- R# D6 n* JDrawDibDraw( m_hDrawDib, dc.GetSafeHdc() 3 P7 X D' W {# l' I( S
, 0, 0, Wid.x, Wid.y, 5 z$ n+ O2 H) S. ]6 R' z( d1 M% T
mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),
" ~1 Z3 H- ]2 c: ?6 c/ n( b1 Z/ ^mPos.x, mPos.y, Wid.x, Wid.y, DDF_BACKGROUNDPAL); - i' b% E! d9 l/ \
} else { ( c; E7 S W4 ]' c" m( o6 m
DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(), , w H1 o4 }( `- O
0, 0, mDispR.Width(), mDispR.Height(),
+ ] X! S7 n: @9 ?5 t7 d' ]mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),
Q v( [9 y$ g! Q8 U7 y; Y: V0, 0, mpBitmapInfo- >biWidth, mpBitmapInfo- >biHeight, 5 U: o- I# h4 w( T$ d; [
DDF_BACKGROUNDPAL); ' f3 B# [0 U% X* N6 r ?
} 7 _9 U- d- a) y$ L/ E1 }0 v6 u
}
5 Z1 j/ N1 R9 Kreturn; ' c* l2 {; {% }3 \3 x$ V4 F H
} : Q6 n; D# p9 Q: L) h
2 r2 D F3 F' r9 g
. o# C! Q. }' v) m1 [, g- k+ q---- 五、使用CViewBimap类显示BMP位图
$ N6 U5 V7 d7 y5 R( v; `7 C7 _---- 1. 在Visual C++5.0中新建一个名称为mymap工程文件,类型为MFC
( B0 p1 t% s6 q1 R2 lAppWizard[exe]。在编译运行通过后,在WorkSpace(如被关闭,用Alt_0打开)点 4 y1 Y6 J) q. C0 N1 u
击ResourceView,点击Menu左侧的+符号展开Menu条目,双击IDR_MAINFRAME条目
% V5 a6 R% j/ G,进入菜单资源编辑,在'“查看(V)”下拉式菜单(英文版为View下拉式菜单)的
2 A8 s8 O' x5 n尾部添加“ViewBitmap”条目,其ID为ID_VIEW_BITMAP。 0 I* n: x. o5 V$ s7 _
; c- J" V V$ o. S+ l$ @
---- 2. 在Visual C++5.0中点击下拉式菜单Project- >Add To project- 0 m' H: z& c M' C" C; p: O5 T
>Files...,将Bitmap0.h和Bitmap0.cpp添加到工程文件中。
5 X2 l; f3 W; a1 e1 s# l
M* C( s9 l! h4 r6 |9 Q---- 3. 在Visual C++5.0中按Ctrl_W进入MFC ClassWizard,选择类名称为
! q Z( _+ _/ Y7 {+ f( k. ACMainFrame,ObjectIDs: ID_VIEW_BITMAP,Messages选择Command,然后点击Add - T( z4 w0 C" t: r- C+ L
Fucction按钮,然后输入函数名为OnViewBimap。在添加OnViewBimap后,在
' _9 l* v" X. h5 @! f5 OMember functions: 中点击OnViewBimap条目,点击Edit Code按钮编辑程序代码 % V% O# P$ `! W8 E# F0 b2 Y& d
。代码如下: 9 ~* J8 i) b* Y& @$ {# h
7 @% k D1 P, B5 c4 k) t1 Q
void CMainFrame::OnViewBitmap() I/ L# J+ E- L5 R/ s
{ & Z$ o- H* l8 D3 T; _. a+ L. V8 X
// TOD Add your command handler code here % T5 u5 B2 o& D
CViewBitmap *pViewBitmap= NULL;
5 f1 u3 |+ v, s* b( G7 ?; l 1 Q1 o/ |) e$ e# o9 U
pViewBitmap= new CViewBitmap( "BITMAP.BMP", this); 1 N* ?7 U3 v8 F: i; d, @2 |/ E
pViewBitmap- >ShowWindow( TRUE);
% p( W- J3 a; m, E5 P+ p}
. M0 w# E% |5 p; z: c
2 u& O2 u! o( ?% p 3 i3 C% E* f7 t
---- 并在该程序的头部添加#include "bitmap0.h",然后编译运行。 + J7 t& o2 m; Z& T: f, u9 W8 T
---- 4. 找一个大一点的真彩色的BMP位图,将它拷贝到BITMAP.BMP中。 " M g/ k5 @2 O4 v {8 V& v* V& b
/ J* d! T0 |+ ^. g---- 5. 运行时,点击下拉式菜单“查看(V)- >ViewBitmap”(英文版为View- > 4 i. V. M1 A: U* E* ]
ViewBitmap)即可显示BITMAP.BMP位图。
% d% b+ Q0 s! o' q) n
, }- M. N, E) m; d: v# |, B# H$ _---- 六、CViewBimap类功能说明 : p4 e7 l* s0 I4 Q$ V7 u( D
' t5 G8 w/ k* d4 [% o---- 1. 在客户区中带有水平和垂直滚动条。在位图大小大于显示客户区时,可
) \ C' f$ G- Q1 S+ c9 j) N$ r以使用滚动条;在位图大小小于显示客户区或全屏显示时,滚动条无效。 . C. J# s# a0 {- p" v$ M- V
# K4 f+ Y9 ?- T" U9 _- x---- 2. 在客户区中底部带有状态条。状态条中的第一格为位图信息,第二格为 6 v5 t. `1 U% `2 g
位图显示方法,可以是使用普通函数或使用视频函数。在第二格区域内点击鼠标 $ ^8 `+ w: b& P/ j
,可在两者之间接换。第三格为位图显示比例,可以是1;1显示或全屏显示。在
3 G) n! {6 j4 h" E5 ^7 a第三格区域内点击鼠标,可在两者之间接换。在全屏显示时,如果位图比客户区
) A1 s7 Q, m; }小,则对位图放大; 如果位图比客户区大,则对位图缩小。 $ E! G+ P v/ W; J! f9 v. t
5 J- V% U: u ^; V1 U% g---- 3. 支持文件拖放功能。可以从资源管理器中拖动一个位图文件到客户区, * U' I" b- y4 y1 [9 r6 O5 `
就可以显示该位图。 4 F l6 L0 M5 Y) s
9 c+ J/ ^" P5 K$ ^8 J---- 程序调试通过后,可以找一个较大的真彩色位图或调整客户区比位图小, * \/ Q3 L5 L; l1 P( J
! T0 f P1 w W2 H4 e
在全屏显示方式下,比较使用普通函数与使用视频函数的差别。可以看出,位图
" v- a0 m3 Q) B$ M9 U( W/ U2 G放大时两者差别不大,但在位图缩小时,两者差别明显; 使用视频函数时位图失
1 W/ s V9 L+ s: N8 R真小,显示速度快。
- D8 U0 x6 _' f. D, i# ?
4 Y( k/ F7 M/ u. M8 Y---- 还可以从控制面板中将屏幕显示方式从真彩色显示模式切换到256色显示模
2 c5 p) _: l7 r式,再比较使用普通函数与使用视频函数显示同一个真彩色位图的差别。现在可 ( Q; p( M, _4 ~2 Q" A
以体会到使用视频函数的优越性了吧。
5 v% p! v l9 A- C5 b1 b1 l
; ?. ?% k* R( A8 L---- 在全屏显示时,位图的xy方向比例不相同,如要保持相同比例,可在显示 * c2 h$ [1 g7 @1 c; x% o6 G
程序中加以适当调整即可,读者可自行完成。 |