|
8 s( v& L R7 T1 k$ [8 ]2 E2 Y+ E
西安交通大学流体机械研究所
* u, ~ }4 M' R- A! _张义云
+ m; m0 F# t- K0 I7 Q. ?! ]
( L5 b( P3 {% U4 u, A---- 用普通方法显示BMP位图,占内存大,速度慢,在图形缩小时,失真严重, + S$ d) c6 }1 @. Z. {
在低颜色位数的设备上显示高颜色位数的图形图形时失真大。本文采用视频函数 - M1 P: ~. @* L) j' ~% `
显示BMP位图,可以消除以上的缺点。 3 j1 i! E3 C' B" Q5 y
' v# P0 K7 j; X" @2 o) K% D
---- 一、BMP文件结构 % _1 X2 R9 V& p; z i% e+ z
! a! |# E8 R; p* R" j
---- 1. BMP文件组成
* N" h+ G! M( D: s3 ^ 2 g" u' }, F* v# a/ S( w0 t
---- BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。
' f+ ? v7 Q" Z: r) b2 o7 p! @ ( k) L+ e2 u1 s
---- 2. BMP文件头
( c' j7 p8 I& B! I" v0 p. I
% s1 s6 ?; ]; H5 W+ `" m+ H+ A' C---- BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息
9 p2 C/ o0 ]) P0 o: K。 5 ~. b" K7 s4 `: J
( g( c( t" x, G" Q
---- 其结构定义如下:
5 J! d! ~: S' g( M+ Q1 z8 E . m* U5 r) J& V6 E' E$ C2 M
typedef struct tagBITMAPFILEHEADER
, l1 O0 d7 I7 c{ # Q& T; R8 i) I! G- o$ w$ V
WORDbfType; // 位图文件的类型,必须为BM
7 o3 q0 J5 S" T# V' Q wDWORD bfSize; // 位图文件的大小,以字节为单位
8 F4 Z/ y- J6 S/ jWORDbfReserved1; // 位图文件保留字,必须为0 % L5 _: m# @, @8 Q+ s" d
WORDbfReserved2; // 位图文件保留字,必须为0
0 z1 W. a, v% o& \3 d2 k2 JDWORD bfOffBits; // 位图数据的起始位置,以相对于位图 7 Q) {1 b; t$ U9 J( H9 y. j
// 文件头的偏移量表示,以字节为单位
$ |, X# p/ L" R, \/ k0 ^; @' E6 _} BITMAPFILEHEADER;
9 _' v4 w8 w; V( b6 @+ V9 p - z) Y: E0 z! G1 ]5 x. M
. o& u& S/ X' Z2 s
---- 3. 位图信息头 * S/ Q# O+ o1 Z3 {& |6 E
---- 0 t) H9 R3 r0 v7 r
R7 k4 h7 _' c1 Y, g& \
BMP位图信息头数据用于说明位图的尺寸等信息。
$ f* `' J% k$ ~% M. f' rtypedef struct tagBITMAPINFOHEADER{ & v2 _* W2 j! w
DWORD biSize; // 本结构所占用字节数 7 y1 r% B3 I1 F) n9 f
LONGbiWidth; // 位图的宽度,以像素为单位
: t7 R7 [: i/ k% u LONGbiHeight; // 位图的高度,以像素为单位 ; t; H1 e$ G; @. @, x
WORD biPlanes; // 目标设备的级别,必须为1
\1 R6 V; i: F, [ P1 A. g WORD biBitCount// 每个像素所需的位数,必须是1(双色),
2 W; b9 \9 _' y // 4(16色),8(256色)或24(真彩色)之一 , w. f/ S& k' }8 n J% f) u
DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),
8 R! @6 }2 i' a // 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
2 K4 m& u e4 v# m3 r, ~" s DWORD biSizeImage; // 位图的大小,以字节为单位
8 d' M. d9 d( V5 I LONGbiXPelsPerMeter; // 位图水平分辨率,每米像素数
9 V. r8 S$ k& p8 A2 d! h, C LONGbiYPelsPerMeter; // 位图垂直分辨率,每米像素数
H6 Q H3 W n1 i DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数 n& } W& B/ @( G% O! N
DWORD biClrImportant;// 位图显示过程中重要的颜色数 + {; s8 [/ @" U
} BITMAPINFOHEADER; 8 h4 t8 j& p& `) b( @
/ g5 }+ K$ c/ ~' a* e
5 g2 u J9 ^ \( N---- 4. 颜色表 2 ]7 A' {4 ]1 D3 c% _; d9 Q
---- 颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个
; A7 z- Y$ v( ^ I+ Z# v6 }8 ]- W* tRGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:
0 \! c; F+ ?+ j, N) b; [% G! g
% s- G9 t% s" s- O' _8 s; wtypedef struct tagRGBQUAD { ' ]5 f% t( ~! B3 a0 q5 X
BYTErgbBlue;// 蓝色的亮度(值范围为0-255)
0 M e2 X) S$ f5 nBYTErgbGreen; // 绿色的亮度(值范围为0-255)
6 L# m" j& a( @2 t6 tBYTErgbRed; // 红色的亮度(值范围为0-255) ; |: h, Y7 t0 _: q& _# }
BYTErgbReserved;// 保留,必须为0 3 y9 \ n5 }0 \- e5 V' w
} RGBQUAD;
$ u- U" \# O! y A9 o颜色表中RGBQUAD结构数据的个数有biBitCount来确定:
- s# l% x3 x/ o6 L; n' p. E当biBitCount=1,4,8时,分别有2,16,256个表项;
" s" ]% j+ r. g8 E. ?0 l; B当biBitCount=24时,没有颜色表项。 + @9 S. ]8 N3 B/ K) b
位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下: 6 ]4 }5 m1 `& ^8 T, C e
typedef struct tagBITMAPINFO {
+ p6 r( P4 D* {7 y BITMAPINFOHEADER bmiHeader; // 位图信息头
: {8 f/ U; x5 b7 Q2 D. g% I0 r RGBQUAD bmiColors[1]; // 颜色表
: f) u4 n+ Z% `+ b4 T} BITMAPINFO;
/ R6 X( h; ~- [, Q# u' ^ g6 E/ j1 M 2 `. A! z$ V$ s8 t2 r! A
+ g/ s+ ~/ M6 q9 D' t+ j5 i
; v& f5 O$ n" U6 q; {---- 5. 位图数据
# w2 p+ h2 n8 l& [/ d; ^---- 位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右
' O7 A& h$ s% [0 ^" t% O,扫描行之间是从下到上。位图的一个像素值所占的字节数: 4 N/ E# w0 c% A3 N/ ?5 f! ^
, x4 \. _% B q6 W/ J
当biBitCount=1时,8个像素占1个字节; " M9 J, x& F0 R0 H z
当biBitCount=4时,2个像素占1个字节; 4 K" \( k4 `0 \# Q$ E v
当biBitCount=8时,1个像素占1个字节; ) x* `; _9 k9 g
当biBitCount=24时,1个像素占3个字节;
. O# F% t& X6 p2 QWindows规定一个扫描行所占的字节数必须是 8 X* U. w9 |. ^
4的倍数(即以long为单位),不足的以0填充, # u4 p9 A. }6 M1 X# b
一个扫描行所占的字节数计算方法: ( ]( R5 k, P4 w7 R8 U( D
DataSizePerLine= (biWidth* biBitCount+31)/8;
4 W! ]) n. d4 w) T // 一个扫描行所占的字节数 : d( g- j# q+ p
DataSizePerLine= DataSizePerLine/4*4; // 字节数必须是4的倍数 3 Z+ O- a' \2 g2 p& |& j5 s' Y
位图数据的大小(不压缩情况下): ) o6 m7 I0 n0 C- u/ q7 k3 N
DataSize= DataSizePerLine* biHeight;
' o0 q- a, @3 g2 G/ B8 Z) ] ; n4 Y: E2 Y% k/ Z# A
; H3 R( L% l8 X---- 二、BMP位图一般显示方法 # J. S! l, k1 u/ x
---- 1. 申请内存空间用于存放位图文件
+ r t7 D$ |- P* `$ p ' O, E# }% u8 {% E* Q d; x- n
---- GlobalAlloc(GHND,FileLength); 6 Z% Y, e6 _2 `$ e' l# p/ I8 Z5 Z
. o5 E) ^2 A; v5 Z9 T---- 2. 位图文件读入所申请内存空间中 + r4 }$ i# b4 L+ }2 r
# i( m6 e5 N! v# f---- LoadFileToMemory( mpBitsSrc,mFileName); 2 }! U0 {! x, f
- n" \2 o- p4 U% E% k: ?3 v2 j8 A6 s---- 3. 在OnPaint等函数中用创建显示用位图 . f% r# H5 h) Q) C: y9 A
$ Q! l. P6 w$ w
---- 用CreateDIBitmap()创建显示用位图,用CreateCompatibleDC()创建兼容 7 ^- r" y' k( E z" @
DC,
0 I+ t2 K$ {% j3 l6 `& | - k8 m0 t4 q7 L' U* Y" h
---- 用SelectBitmap()选择显示位图。 ; V7 O/ H4 _" q% L8 k# k+ A
' z# \" @" X/ ~. W9 n2 K
---- 4. 用BitBlt或StretchBlt等函数显示位图
% n, Z/ g! r; B3 f, R
4 Q; B- y5 Q% i3 `4 G0 c# ]) ~: |---- 5. 用DeleteObject()删除所创建的位图 $ f0 T+ K, {6 }! T! A
, W% {& \& l3 f: F9 A" j
---- 以上方法的缺点是: 1)显示速度慢; 2) 内存占用大; 3) 位图在缩小显示
( C* J! h5 o5 j. S时图形失真大,(可通过安装字体平滑软件来解决); 4) 在低颜色位数的设备上(
% O9 @3 G% q: G4 X* ~& Y如256显示模式)显示高颜色位数的图形(如真彩色)图形失真严重。
5 G* `# o8 K( D) n* t7 K5 e) P # Q3 I( b, K8 Y7 \& Q8 S% q7 ^
---- 三、BMP位图缩放显示 / f5 S9 ?- f% c e; C! ^
9 l+ i, a1 [+ _; s8 i---- 用DrawDib视频函数来显示位图,内存占用少,速度快,而且还可以对图形 & c [+ L D0 N D9 A1 O
进行淡化(Dithering)处理。淡化处理是一种图形算法,可以用来在一个支持比 $ \( i4 ?) i! I' n# Q
图像所用颜色要少的设备上显示彩色图像。BMP位图显示方法如下:
E3 @, {& w( a/ B ; P. Y4 J1 R. e
---- 1. 打开视频函数DrawDibOpen(),一般放在在构造函数中 * M& |* O3 B. h' a C
% X8 V( V/ U* o! ]# ^---- 2. 申请内存空间用于存放位图文件 $ s V+ q8 f7 d8 z3 ?1 O
2 {# \: t- o4 J# l) C: p8 ?
---- GlobalAlloc(GHND,FileLength);
+ A% v: X. W- n6 G" `
% i. C1 {/ r5 o- U5 [2 [, E---- 3. 位图文件读入所申请内存空间中 & R+ g+ n% A3 W
1 Q% H( C. t8 Z
---- LoadFileToMemory( mpBitsSrc,mFileName); - J' `9 W. N7 x+ v% y7 N
/ v1 p5 s1 ]; V+ `+ ]7 w
---- 4. 在OnPaint等函数中用DrawDibRealize(),DrawDibDraw()显示位图
3 Z3 b) T0 A: H& b" \) A( E
4 C9 c8 t+ E0 w1 e---- 5. 关闭视频函数DrawDibClose(),一般放在在析构函数中 9 u' f( c) A) m$ v
5 i( l* }* x% l+ f( B3 Z---- 以上方法的优点是: 1)显示速度快; 2) 内存占用少; 3) 缩放显示时图形 * |% y0 u. n- ]; r/ S- q
失真小,4) 在低颜色位数的设备上显示高颜色位数的图形图形时失真小; 5) 通
8 q% j/ q; U ~. T+ d5 Q- ~过直接处理位图数据,可以制作简单动画。
" R3 d4 g# N# [8 y5 n 9 o8 F1 D, s& l k" l! [5 V
---- 四、CViewBimap类编程要点 & X# u Q, p! Z3 Y& `& X
% O' ^* c9 ?0 s3 V
---- 1. 在CViewBimap类中添加视频函数等成员 . y& M3 H8 `8 m) ^ [0 L& p9 G
6 g6 [1 A6 r# B) k7 \HDRAWDIB m_hDrawDib; // 视频函数 - A2 Y! P" v/ T0 [
HANDLEmhBitsSrc; // 位图文件句柄(内存)
$ R- D! ^& ?4 a6 h, CLPSTR mpBitsSrc; // 位图文件地址(内存)
i) Y5 A" f4 i# w5 q+ q$ }BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头 & K, j0 G6 S, ~3 k' R1 Y
f" R: K; L2 h9 n: V$ U1 g
- i) a& I$ i& E6 [1 m0 ~; e _
---- 2. 在CViewBimap类构造函数中添加打开视频函数
) n& P6 ? M3 ]( n---- m_hDrawDib= DrawDibOpen();
# b7 }# R. r- O; c3 @+ H$ p9 W* q : U4 U7 B ~3 _* `, @
---- 3. 在CViewBimap类析构函数中添加关闭视频函数 ' X, ?4 o- e- |8 |( n+ Z: U9 z5 N
d( h' q- {6 N4 Mif( m_hDrawDib != NULL)
. c0 R$ t, Z! N' g2 @3 a { # Z0 w5 u( [/ s$ ]0 H5 p- v+ X
DrawDibClose( m_hDrawDib); 4 U7 E1 f3 P" L
m_hDrawDib = NULL;
# J# S9 w J/ n4 I }
) ?7 _& }9 i/ A+ f/ x X0 N% y R/ K$ `" o5 l/ S9 g6 x, N1 D
p3 ?8 n+ Q6 e+ L1 _5 D' I
---- 4. 在CViewBimap类图形显示函数OnPaint中添加GraphicDraw() 3 c. x# X- h4 ]+ F) A' ^1 Y7 ]/ U
voidCViewBitmap::OnPaint() % S; `! n0 C% G. o( U
{
; o+ W2 P) G, z/ g0 U: fCPaintDC dc(this); // device context for painting + j" \ l7 I3 s4 n# V5 Z, u: e, T
GraphicDraw( );
% ~2 P2 v$ g$ F$ p} 9 E5 }3 z' P% k9 m
2 E4 I6 G9 Q8 O( o' H( u2 A& b' c
voidCViewBitmap::GraphicDraw( void ) 8 C) o' P0 C& t7 L; q' v v N
{ 7 I3 C3 N9 g; i* M7 J: G
CClientDC dc(this); // device context for painting + o1 H' q# n6 k2 y7 \
BITMAPFILEHEADER *pBitmapFileHeader; 8 [, W- \3 e( d# F% r# y$ t% F; E
ULONG bfoffBits= 0;
' p' T9 N) a' y" v; Q3 aCPoint Wid;
& K9 ^$ `0 h3 x3 z' n2 P; V/ v 9 c/ y" i" y% [4 c( [
// 图形文件名有效 (=0 BMP) % |3 ]: x0 ]" I) N! y+ _' M
if( mBitmapFileType < ID_BITMAP_BMP ) return;
# I+ Q2 A" [0 K/ J " f, o! \; k j! f, c4 ^3 ?! K
// 图形文件名有效 (=0 BMP)
9 a O0 K+ Q. W. t; y* B// 准备显示真彩位图
( U# @1 i) q4 k( n/ `9 a! PpBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc; 3 f7 Z$ j. N* S h
bfoffBits= pBitmapFileHeader->bfOffBits; 9 ]2 ^6 f3 C5 G& @4 ~
+ L; c8 b2 S0 K; r
// 使用普通函数显示位图 6 K" ]( @" a3 ^# F: j
. V1 e2 g8 F6 \: {! _: \& Hif( m_hDrawDib == NULL || mDispMethod == 0)
4 {; P+ P& D3 D6 s' z {
; ~; n# I# H: Q4 z2 J& x HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC, 0 w8 g$ f2 Q$ D) |+ A0 m
mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits, 6 g2 F3 Z9 q; s
(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS); 3 d& D" k* r: I) K/ B$ c
// 建立位图
F5 t8 w4 X$ K% aHDC hMemDC=::CreateCompatibleDC(dc.m_hDC);// 建立内存 7 b. \1 J0 j- j/ u; v1 J; u
HBITMAP hBitmapOld= SelectBitmap(hMemDC, hBitmap); // 选择对象
- F3 n* L6 s Q7 E// 成员CRect mDispR用于指示图形显示区域的大小.
E+ N; G; b- U5 M& C// 成员CPoint mPos用于指示图形显示起始位置坐标.
# s% O9 e- M8 P; ]: v( L, J. bif( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() )) 0 o6 m* ~3 J* p/ r3 ~; N( t
mPos.x= mpBitmapInfo->biWidth - mDispR.Width() ;
! [. D, a+ y7 M/ p if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height())) 5 {3 ~$ x1 N9 j6 b% x! h% F
mPos.y= mpBitmapInfo- >biHeight- mDispR.Height();
9 y1 u* n! P- _9 |4 }5 w" d if( mPos.x < 0 ) mPos.x= 0;
7 T0 e! y5 _! ?) d if( mPos.y < 0 ) mPos.y= 0;
" B/ G9 h1 Y. A) V R D4 X% m* B6 U% E; X$ u
if( mFullViewTog == 0)
- e7 l% b1 y6 O5 R" D0 X{ 5 e# \* f! v- M" O U. G. g' h1 g$ s
// 显示真彩位图
6 d# }( T0 Y' Q* V' G# X7 E::BitBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(), + p- b& c, X* m9 r- F
hMemDC,mPos.x,mPos.y, SRCCOPY);
" @* U" i& W x} else {
3 @5 q; j7 o4 S" k) g% T5 v::StretchBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),
9 C3 f* N$ K9 ]4 BhMemDC,0,0, mpBitmapInfo- >biWidth, mpBitmapInfo- , f7 i& l, A8 f1 r) s/ J
>biHeight, SRCCOPY); 7 ?& L: @8 u4 c8 o1 e
}
! y! v0 U2 Z& o9 w+ _- s+ S5 C // 结束显示真彩位图
2 O9 W" r# W$ I# K : eleteObject(SelectObject(hMemDC,hBitmapOld));
; ~& t3 y4 I% n: _7 `8 z// 删 除 位 图
; j1 S- c- y3 h; O9 e } else {
5 |( f6 m$ M+ X3 o) Z7 b5 Z
3 t7 C7 m3 c; k& j // 使用视频函数显示位图 8 k- z. p! J. m. b( k
# _$ {3 V! V1 V$ q3 V8 O if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() )) - j/ j. h! k8 K" s6 L4 w' x& a$ w
mPos.x= mpBitmapInfo- >biWidth - mDispR.Width() ;
4 [" K9 Z! f# `/ u6 m% h/ ? if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height()))
$ q: E( e1 u5 e$ \& h$ R/ ]- VmPos.y= mpBitmapInfo- >biHeight- mDispR.Height();
# s" ~" ^& W2 ?1 ]1 W if( mPos.x < 0 ) mPos.x= 0; 7 T5 a; t: x6 x$ H" }
if( mPos.y < 0 ) mPos.y= 0; , n" f/ N+ u W( c. F1 M/ H, x
6 [* o. T! ^2 U( t5 u: o' m9 m* N
// 显示真彩位图
8 X. j* y& }. L- }- S! b8 E DrawDibRealize( m_hDrawDib, dc.GetSafeHdc(), TRUE);
; d4 a; P2 C! I4 z; B: X
8 f# r7 C9 O+ O7 E if( mFullViewTog == 0)
2 N% v6 K9 z; Y3 c{ ) Z1 [& @( m9 g
Wid.x= mDispR.Width();
_0 A0 N9 o+ x u4 FWid.y= mDispR.Height(); ; S/ R- t8 l1 m5 g& g6 Z
// 1:1 显示时, 不能大于图形大小 4 q- h- y+ k' C" e: J" o
if( Wid.x > mpBitmapInfo- >biWidth )
! M% I" }6 j ?" ^: AWid.x = mpBitmapInfo- >biWidth;
- T) ^6 s- r- s, d7 b$ D2 uif( Wid.y > mpBitmapInfo- >biHeight) 4 l3 j7 |: B+ @# Z5 }
Wid.y = mpBitmapInfo- >biHeight;
/ p8 b$ e$ ` `8 R6 r; l1 W% }
3 w, x, {' ]0 bDrawDibDraw( m_hDrawDib, dc.GetSafeHdc()
6 V+ ~- a/ a$ U `6 [5 j, 0, 0, Wid.x, Wid.y, , U8 Q# g: r& ]8 J* J; F4 E+ T
mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits), 3 v' j( X- D! [2 `" h6 \3 V0 m
mPos.x, mPos.y, Wid.x, Wid.y, DDF_BACKGROUNDPAL); * L* C5 [1 j- A% |% X) u5 R
} else {
* z' i- Y( _% k5 h# {! L3 z- V9 j& nDrawDibDraw( m_hDrawDib, dc.GetSafeHdc(), . n- S. u3 I/ S% I( v
0, 0, mDispR.Width(), mDispR.Height(),
& `* b$ m& b% m+ G- u3 v( s! YmpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),
: }! x; \' a8 I L8 Y0, 0, mpBitmapInfo- >biWidth, mpBitmapInfo- >biHeight, ( G! T% `5 F9 J, g a
DDF_BACKGROUNDPAL);
7 ]$ q5 {0 I6 z' l} # I, n5 i5 n- L4 k9 I S) H
}
. _( k" a9 f, `return;
# Y. |6 ]" s2 c5 f; o}
- g3 Z( m: t: o+ q. B) B
$ U) @- D. u( A
9 J. b! g. F) d' J, V---- 五、使用CViewBimap类显示BMP位图 * w& A/ D/ w. D: m6 f& l
---- 1. 在Visual C++5.0中新建一个名称为mymap工程文件,类型为MFC
/ M8 J8 M. z' l9 CAppWizard[exe]。在编译运行通过后,在WorkSpace(如被关闭,用Alt_0打开)点
" X' w% j7 M$ N. d击ResourceView,点击Menu左侧的+符号展开Menu条目,双击IDR_MAINFRAME条目 % I# O# S" x+ ]6 Y' a
,进入菜单资源编辑,在'“查看(V)”下拉式菜单(英文版为View下拉式菜单)的 " j& }0 [, n; [3 A- `) g2 l6 N: Z
尾部添加“ViewBitmap”条目,其ID为ID_VIEW_BITMAP。
/ q& k6 @ B* b' N2 d8 r) L ' O3 g) C4 b2 ]( S/ u0 i/ a/ D
---- 2. 在Visual C++5.0中点击下拉式菜单Project- >Add To project-
?) ^3 L2 J' m* j& Z1 T! k! r>Files...,将Bitmap0.h和Bitmap0.cpp添加到工程文件中。 . r' y( J6 E7 [& f
! I4 L9 X) u: L
---- 3. 在Visual C++5.0中按Ctrl_W进入MFC ClassWizard,选择类名称为
. e7 Z% O1 c+ qCMainFrame,ObjectIDs: ID_VIEW_BITMAP,Messages选择Command,然后点击Add
: c4 X e3 O1 u% B9 { Fucction按钮,然后输入函数名为OnViewBimap。在添加OnViewBimap后,在 + R' B' H3 v, t6 C! a* ]8 V0 {* M
Member functions: 中点击OnViewBimap条目,点击Edit Code按钮编辑程序代码 3 m" M m# W. E) O+ T1 c; f* [
。代码如下: ( e) c& B6 q" R7 \) {' Y% j
( m3 Z7 L- _6 f) A1 S3 [7 E6 ~void CMainFrame::OnViewBitmap()
- s; U* v3 R7 c{ 0 L8 ]( e4 p. Q7 x0 H9 t/ b7 [
// TOD Add your command handler code here ! Y5 l& A8 C+ \+ `
CViewBitmap *pViewBitmap= NULL; 2 A Z% _! Q7 F
2 O( E+ J1 ]2 \! v3 L( hpViewBitmap= new CViewBitmap( "BITMAP.BMP", this); ' m0 {* N& }( c
pViewBitmap- >ShowWindow( TRUE); # W$ f- S6 J/ K
} 4 M' c3 L' h1 E1 g* m
& C+ N% E2 [0 Q( R, B9 e
' t8 |1 f+ e: n8 p0 p% N---- 并在该程序的头部添加#include "bitmap0.h",然后编译运行。 % D6 l+ J) |: H7 @$ R0 D' [$ h& R
---- 4. 找一个大一点的真彩色的BMP位图,将它拷贝到BITMAP.BMP中。
# q' S9 ?3 J0 z' I' b6 V
0 P5 h8 `3 d. d+ Q9 h---- 5. 运行时,点击下拉式菜单“查看(V)- >ViewBitmap”(英文版为View- >
, ^& R3 m5 s. z% E: _! V( A ViewBitmap)即可显示BITMAP.BMP位图。
5 l0 P. ?/ e- V! q4 Z- `4 @
2 C6 X j; P2 m! R; H, ?+ {% W---- 六、CViewBimap类功能说明 0 o u7 _7 _" Y! X% x" F8 y7 i
) ~; X1 x) K; U0 @1 g8 V) ~8 n% n) l---- 1. 在客户区中带有水平和垂直滚动条。在位图大小大于显示客户区时,可 " P9 t5 {5 x3 m
以使用滚动条;在位图大小小于显示客户区或全屏显示时,滚动条无效。
0 K' N' q5 [# c; ?2 L) R / O' C- N+ [1 J8 {' G6 S
---- 2. 在客户区中底部带有状态条。状态条中的第一格为位图信息,第二格为 ! q6 t2 D# A: ]& p8 }2 w
位图显示方法,可以是使用普通函数或使用视频函数。在第二格区域内点击鼠标 + g9 r7 s4 A0 l% H5 Q Z. i. p
,可在两者之间接换。第三格为位图显示比例,可以是1;1显示或全屏显示。在 7 t! p+ `) |. m! N, Y7 {3 p2 _
第三格区域内点击鼠标,可在两者之间接换。在全屏显示时,如果位图比客户区 0 }: i; g0 ]" u
小,则对位图放大; 如果位图比客户区大,则对位图缩小。
8 ]6 r3 s+ Y. z: k ; L, p' r! q# \( s- x- Q1 o; z
---- 3. 支持文件拖放功能。可以从资源管理器中拖动一个位图文件到客户区, 9 e$ ^+ s! g% I: g7 B: {( j
就可以显示该位图。
8 L( N8 Z2 o! t2 g! `" {
5 j- N6 Z) m7 Y# m5 D0 Y+ o' `' U---- 程序调试通过后,可以找一个较大的真彩色位图或调整客户区比位图小, * m, s2 M& p, I% [5 b
W9 U- O( z- f在全屏显示方式下,比较使用普通函数与使用视频函数的差别。可以看出,位图 & _" W8 ?: l% a0 Z" x- @: f4 ?
放大时两者差别不大,但在位图缩小时,两者差别明显; 使用视频函数时位图失 3 D6 g* u# z j5 i2 g
真小,显示速度快。
9 C, Z5 J# W3 q2 c( ]5 {+ T n/ s 5 N% w5 Y$ G; D5 h$ q
---- 还可以从控制面板中将屏幕显示方式从真彩色显示模式切换到256色显示模
! ?& y' @8 ?. Q# |. ^) z式,再比较使用普通函数与使用视频函数显示同一个真彩色位图的差别。现在可
! @. g6 [* Z6 p8 o! A" @ L以体会到使用视频函数的优越性了吧。
4 C8 I" d! q3 a" T8 v8 B # k) x% @4 t7 R& O' O' }# }. X4 ?
---- 在全屏显示时,位图的xy方向比例不相同,如要保持相同比例,可在显示
8 E" \% k. k( R+ O5 i程序中加以适当调整即可,读者可自行完成。 |