|
' G& h* g% A/ I# H' {西安交通大学流体机械研究所
8 s1 A5 D: D/ ~6 o8 V: B) s! B张义云
$ N' R5 D& H% R6 H0 C& N9 b ; Q" Z4 ~, S3 U& h1 f& {& T5 J1 n
---- 用普通方法显示BMP位图,占内存大,速度慢,在图形缩小时,失真严重,
, P" X, T. o& K9 z在低颜色位数的设备上显示高颜色位数的图形图形时失真大。本文采用视频函数 - O, t# \6 y6 @# m
显示BMP位图,可以消除以上的缺点。 9 N6 _$ i( g- x( m0 \7 l; q% c$ M3 r
/ l5 j8 _7 j2 j3 I% Y---- 一、BMP文件结构 - t) m5 s' j7 X) Z/ m5 w
+ l& U# A9 J; e5 ^( Z+ q---- 1. BMP文件组成 # }$ V& b9 }" C# V9 } U' ]9 ~7 }8 |
0 o0 e$ [- L# H( K/ \/ b! m
---- BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。 ) {6 w* n' z5 @* U4 t+ v$ g
; E$ { b2 e5 N5 f; G
---- 2. BMP文件头 ; ~3 G: H% e- `3 |( v) i1 t
5 c0 i5 B* i6 o( @+ P8 E, Z
---- BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息 ; U0 o& W4 W# h ]3 e- E$ i7 k
。 $ B' T: S+ {2 T, L! F
' @: s1 H. Q) T4 W$ a; i
---- 其结构定义如下:
1 s6 d4 _5 s1 G7 s& x1 { * e% f, H' i8 E" K2 X
typedef struct tagBITMAPFILEHEADER % A& f5 w3 j/ P% s# W8 \; I
{
3 A6 ]0 X6 N& m; \+ Z4 ^0 c) u& OWORDbfType; // 位图文件的类型,必须为BM
- q2 E5 r. b) m/ {DWORD bfSize; // 位图文件的大小,以字节为单位
% e% v0 W7 `) h& ^$ B1 g8 vWORDbfReserved1; // 位图文件保留字,必须为0 4 C1 v5 m! c+ ]1 P3 H& a) h3 |
WORDbfReserved2; // 位图文件保留字,必须为0
' E3 z ]' o @; fDWORD bfOffBits; // 位图数据的起始位置,以相对于位图 ; K8 e7 Z! A/ ^" H1 U& c3 r
// 文件头的偏移量表示,以字节为单位
- t" L* v/ b1 P. X- o) m} BITMAPFILEHEADER; 7 ^. ~/ z9 A y: ~+ u8 l# @
' Q6 n: m& B4 i3 ]1 g; A' i+ C
$ a& G; ?- ^- k9 H" X3 E, d2 S
---- 3. 位图信息头
. [; i! t. Z$ |* ^9 f. c& p----
' G$ A/ ]& j9 ]7 ^9 t
9 ]$ Q) V6 p9 ]3 E) S- m4 rBMP位图信息头数据用于说明位图的尺寸等信息。
9 ^, k2 a# u% rtypedef struct tagBITMAPINFOHEADER{ 2 X0 z5 S8 v# L/ m
DWORD biSize; // 本结构所占用字节数 & C! U6 A% l* x4 Z2 a
LONGbiWidth; // 位图的宽度,以像素为单位
3 g6 t0 e: F# k+ ? LONGbiHeight; // 位图的高度,以像素为单位 & v1 t% k g6 k5 B& g7 \
WORD biPlanes; // 目标设备的级别,必须为1 . j- F( \/ W- b" s& r9 z; h
WORD biBitCount// 每个像素所需的位数,必须是1(双色),
. e7 ~3 |* Q1 Y0 v: n // 4(16色),8(256色)或24(真彩色)之一
5 a- P; p" p. T' @0 k) ?& N DWORD biCompression; // 位图压缩类型,必须是 0(不压缩), ( W) l( c5 K- Q1 O
// 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一 ) R8 V6 T" `) A# r# Y- B5 U/ U
DWORD biSizeImage; // 位图的大小,以字节为单位 " a6 j0 j3 m* Y5 B
LONGbiXPelsPerMeter; // 位图水平分辨率,每米像素数
& f, k$ b8 I6 G& j! q) D+ {% g LONGbiYPelsPerMeter; // 位图垂直分辨率,每米像素数
+ e) m1 u% J1 I8 N. N DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数 - n+ u- w2 k, r, q2 {" M2 m% A
DWORD biClrImportant;// 位图显示过程中重要的颜色数
3 J U: s; G3 z, A& J& X4 v} BITMAPINFOHEADER; / J( W E, q+ E2 n* G
) X5 V* v2 T9 m# {9 S- a0 F2 f
% K& x0 d8 B, C
---- 4. 颜色表
) n7 c# A2 x' r; h+ Z+ T7 f' W---- 颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个
$ `$ K3 s* i5 p$ R% v A; I" CRGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下: [0 A. _5 q: F$ q' S9 q2 P- o
6 m, d+ n- `9 J+ S: ]; ]typedef struct tagRGBQUAD {
; {. Y. C; y8 t5 z( FBYTErgbBlue;// 蓝色的亮度(值范围为0-255) 5 y, B" ?4 X; Y& R3 m
BYTErgbGreen; // 绿色的亮度(值范围为0-255)
1 G4 A y) N. D, E% o0 T0 kBYTErgbRed; // 红色的亮度(值范围为0-255)
% o" B' v& d d$ v4 z5 yBYTErgbReserved;// 保留,必须为0 ' V. ^) H6 w# z& { j
} RGBQUAD; 0 r2 L' Y0 X& T+ U1 }/ r' C% F2 R
颜色表中RGBQUAD结构数据的个数有biBitCount来确定: & G R: F8 Y5 ~, G$ `# r! C( g, K
当biBitCount=1,4,8时,分别有2,16,256个表项;
" T9 v7 t. O5 i% w当biBitCount=24时,没有颜色表项。 & E/ {) Z" b2 Y2 Y: {' Q
位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下: 8 z. k; U0 ^; W$ k
typedef struct tagBITMAPINFO {
- }3 e6 ~# U( M0 f9 _: f BITMAPINFOHEADER bmiHeader; // 位图信息头
2 e1 f- M+ W+ y' [: i" l( t RGBQUAD bmiColors[1]; // 颜色表
) P) c5 D- ~9 R+ x0 G& y6 J; L6 m} BITMAPINFO; , v* i% y' W4 x3 h
0 D9 M) v8 u' Z8 Y! v
9 R* t( J& l* H% \ & Q0 s* u5 ]1 Q( ^4 Q
---- 5. 位图数据
" l4 ]9 |& a. c1 t# S% Y8 X& X" c---- 位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右
/ w; f$ X1 y6 o" n" X,扫描行之间是从下到上。位图的一个像素值所占的字节数:
0 n% N q2 u! y0 P; c" p
6 s) V7 E3 G/ Z6 ?5 K- w' R当biBitCount=1时,8个像素占1个字节;
* y, D6 l4 C' T. e% g5 ^, n: L当biBitCount=4时,2个像素占1个字节;
( C2 `( ~3 y% c% M! m当biBitCount=8时,1个像素占1个字节; / G( d/ |, @4 O3 ?3 z
当biBitCount=24时,1个像素占3个字节;
0 y7 C/ d! l+ F! B5 MWindows规定一个扫描行所占的字节数必须是 ' [+ q3 Z& i: ~: R( _9 a) f3 V
4的倍数(即以long为单位),不足的以0填充, - l- o4 a$ D3 n2 o+ B& p
一个扫描行所占的字节数计算方法:
8 s* O3 t* f0 x# J' `, RDataSizePerLine= (biWidth* biBitCount+31)/8;
- e! M2 t' ^: L& U1 H2 ?" k9 y // 一个扫描行所占的字节数
) ^& w% C3 P" A9 ~DataSizePerLine= DataSizePerLine/4*4; // 字节数必须是4的倍数
0 l7 f8 {" K2 O位图数据的大小(不压缩情况下):
* N/ H- p: v) K& P0 [DataSize= DataSizePerLine* biHeight;
4 U( j' V9 n+ g3 t
" |5 I6 U: c* [ % `& Q/ d4 W, ^; F
---- 二、BMP位图一般显示方法
& m$ {- d& M: u, f% h5 t---- 1. 申请内存空间用于存放位图文件 9 t, W( S; {0 T1 K0 \
# G6 n; r7 E( Y+ A' R' O9 v7 g2 P---- GlobalAlloc(GHND,FileLength); 4 K4 @2 Z _; o6 I
! O9 @7 b$ ^6 R# {# @2 r9 W: G k---- 2. 位图文件读入所申请内存空间中 % k$ a5 Y! j; |- J+ X% Q3 ^
5 b+ V4 W9 ~6 m0 U, D
---- LoadFileToMemory( mpBitsSrc,mFileName); ' p u3 P4 j- @- D$ z$ `4 Q9 t
3 p7 L9 j4 T; m/ T( }
---- 3. 在OnPaint等函数中用创建显示用位图 2 J3 J+ U1 w1 ~6 P
" y# N3 g# j- c; U$ s3 Q7 P---- 用CreateDIBitmap()创建显示用位图,用CreateCompatibleDC()创建兼容
; ~; q- B& I$ zDC,
' l. q/ r) }' ^) ? 0 C }6 n( w2 X
---- 用SelectBitmap()选择显示位图。
" ?0 ?2 m+ O7 D
) d+ P4 D* l3 S E---- 4. 用BitBlt或StretchBlt等函数显示位图
2 F" j. ] v8 u7 Q) ^* k& F
1 ]( s z1 b+ L7 u9 |/ m---- 5. 用DeleteObject()删除所创建的位图
~9 \, f& u& z: R1 q# `
' }) l+ G P0 h' [& H( \---- 以上方法的缺点是: 1)显示速度慢; 2) 内存占用大; 3) 位图在缩小显示 & ]' L- f3 o f. _
时图形失真大,(可通过安装字体平滑软件来解决); 4) 在低颜色位数的设备上( ! F7 V9 \$ ^. b; ]+ N* }0 i a
如256显示模式)显示高颜色位数的图形(如真彩色)图形失真严重。
1 W( S0 s5 k; P4 z& x% } " d* }& N8 M3 l
---- 三、BMP位图缩放显示
; i/ e. {% _: b ]0 P- T" _8 w& X
---- 用DrawDib视频函数来显示位图,内存占用少,速度快,而且还可以对图形
3 d2 e0 o7 n8 `1 ^- C进行淡化(Dithering)处理。淡化处理是一种图形算法,可以用来在一个支持比
+ w) N5 ]' A4 r6 T, _图像所用颜色要少的设备上显示彩色图像。BMP位图显示方法如下:
7 ~, W3 U+ j# r# C% K! k G' ^
$ ?) G0 X' c- ^ U& \---- 1. 打开视频函数DrawDibOpen(),一般放在在构造函数中
4 X) X* w7 ^* h- c 4 O9 M# _+ J( O( b$ I6 E: d* S
---- 2. 申请内存空间用于存放位图文件
7 |. x2 X% t! m4 d . a$ Q/ Y c3 W2 u0 A, E7 B& n
---- GlobalAlloc(GHND,FileLength);
' {) {% [( W3 Z6 A& i" q
. o2 Z# t: P% D5 x, @: ?! l% M% d---- 3. 位图文件读入所申请内存空间中
4 A8 U0 z1 l+ W) f/ V$ f
. o: R; [) ~% F3 l$ A9 b---- LoadFileToMemory( mpBitsSrc,mFileName); ; K2 [( @! U; \8 V$ V
s3 N7 r5 W, ~2 O5 d. O0 q---- 4. 在OnPaint等函数中用DrawDibRealize(),DrawDibDraw()显示位图 4 p; V: c5 ?9 N" y
. }! k A# C" J# a J3 z2 M- {---- 5. 关闭视频函数DrawDibClose(),一般放在在析构函数中
* I9 T' Y# `) o" } 7 W& M. i+ D2 Y7 i$ C3 k) s
---- 以上方法的优点是: 1)显示速度快; 2) 内存占用少; 3) 缩放显示时图形 5 ?& M0 J% r% n# E, R
失真小,4) 在低颜色位数的设备上显示高颜色位数的图形图形时失真小; 5) 通
. a6 K# `% u1 Z2 V& ~! x过直接处理位图数据,可以制作简单动画。
6 S& X5 v9 I; D$ u% m, A) p: J2 M: D - r# `! P) ?6 r4 t. _
---- 四、CViewBimap类编程要点
2 I2 g- }7 k/ N7 O& y5 e) R3 s
4 ]* w& U% ?% U6 X1 Y---- 1. 在CViewBimap类中添加视频函数等成员 % P/ }% G' U. v m1 ~* ]
8 ?! s! L4 |; ~! ^" w
HDRAWDIB m_hDrawDib; // 视频函数
6 g4 I5 @2 |* ~HANDLEmhBitsSrc; // 位图文件句柄(内存) 4 \3 k5 t0 [# P1 o) M v
LPSTR mpBitsSrc; // 位图文件地址(内存)
/ u! B) S! O/ M7 Q# ~BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头 : ]7 \% `3 v% @( @$ Z7 \
' q6 s+ k3 W/ ]6 l$ F Y0 J2 T/ X, \
! e( I4 K9 T( Y1 Z2 L---- 2. 在CViewBimap类构造函数中添加打开视频函数 ' b5 ~2 d& D3 w) x% ?
---- m_hDrawDib= DrawDibOpen(); 1 B) A- f# f" F
! v) d! q( G8 U) U( Z( e---- 3. 在CViewBimap类析构函数中添加关闭视频函数
" b+ R& p7 ^4 B |7 U+ y- g
5 ~/ ~! `1 o: P2 j8 w+ Aif( m_hDrawDib != NULL)
, }: B1 R& q* K/ m8 h7 {4 s { / ~' I ], M' `& r/ y* f/ B5 `/ G7 l) Q
DrawDibClose( m_hDrawDib); 9 x' C1 b8 F7 j! X
m_hDrawDib = NULL;
; n0 E$ {/ j* b9 V* f5 i& F( u }
4 a4 x3 S; R; U# F5 W; Q
9 K2 g' z& x8 O9 ^- R: }, x8 |
4 @. r2 g* @8 T+ v---- 4. 在CViewBimap类图形显示函数OnPaint中添加GraphicDraw()
7 Y7 ?& D' E+ ZvoidCViewBitmap::OnPaint()
( _5 N0 z& m4 ~{ " D, C! G1 |" C$ I4 w+ R+ L
CPaintDC dc(this); // device context for painting
: O5 z3 _" u, ]* L1 s6 M) Z3 TGraphicDraw( ); z: W2 e& C: a5 g* c u& o" J. k
}
* g$ d" o/ E0 L3 L+ z7 l8 n
) U6 d& v+ h/ F0 M9 {, t; G) @voidCViewBitmap::GraphicDraw( void )
4 @0 L, M/ O- L3 P{ . }7 A* M4 _8 Z+ f0 _6 S5 f: I
CClientDC dc(this); // device context for painting
. E+ W, ~6 J) h1 q7 oBITMAPFILEHEADER *pBitmapFileHeader; % C( T' |, T7 K
ULONG bfoffBits= 0; ( ~2 D. b4 n8 Z! V
CPoint Wid;
' s9 E/ W; [- r 8 P" @; N( i0 D% ~: ]. U8 o5 u" S
// 图形文件名有效 (=0 BMP) ; d8 ]" S' Q+ ?9 g' X1 M
if( mBitmapFileType < ID_BITMAP_BMP ) return;
3 K( x$ W/ p% H
( N7 V8 `8 ^& G5 H& p/ E. j" M// 图形文件名有效 (=0 BMP)
- T( b2 y- T4 j9 P4 N) G' c. }$ s// 准备显示真彩位图 - B$ }" I, t& l0 s; {, v
pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc; 9 V4 x$ y+ d( \
bfoffBits= pBitmapFileHeader->bfOffBits; ; t9 K& Z9 j. h6 V. L; s: t' C
9 K$ f' F! n4 M1 d5 H' b2 f) u// 使用普通函数显示位图 ( ?5 }. O& o) I1 x8 v- k6 e% Z. S: K
+ O w2 f0 e4 f- O$ i8 q3 f" l
if( m_hDrawDib == NULL || mDispMethod == 0) ! D, _( h1 h) j
{
) b" F; | ?: o8 Z1 R HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,
7 r7 L& @# x1 R, MmpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits, # N/ ^2 d% E+ u6 i; x$ i9 S2 {
(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);
5 i6 i5 P. j' K }// 建立位图 3 R, J: l/ M w
HDC hMemDC=::CreateCompatibleDC(dc.m_hDC);// 建立内存
" Q3 J$ Q* X& V$ uHBITMAP hBitmapOld= SelectBitmap(hMemDC, hBitmap); // 选择对象
* n. ~7 V1 D8 D1 a7 j# ~3 A// 成员CRect mDispR用于指示图形显示区域的大小. % I6 B( k" r9 {
// 成员CPoint mPos用于指示图形显示起始位置坐标.
7 k, q. ?, h, N$ Fif( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() )) 1 i) I1 Z0 l1 S6 @! J
mPos.x= mpBitmapInfo->biWidth - mDispR.Width() ;
5 I# A7 @1 E$ _. _. K1 V if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height())) # f) ?" I9 p( a: U0 m
mPos.y= mpBitmapInfo- >biHeight- mDispR.Height();
& @1 Q: m- j% W( z6 U' e2 A if( mPos.x < 0 ) mPos.x= 0;
. g2 u5 N+ U: K$ p if( mPos.y < 0 ) mPos.y= 0;
% k; P, U& M) p U( I ; h5 ]9 D6 F, {2 t* H2 M
if( mFullViewTog == 0)
0 ~9 T: d/ o, ?. T7 T- \{ - q2 v+ f. k" {+ u9 l
// 显示真彩位图 6 ?* `8 ]. P; o* u
::BitBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),
# O9 P' d, z. W1 n% ? w ]5 ]hMemDC,mPos.x,mPos.y, SRCCOPY); / g7 O }; J; B! Z/ _
} else { m3 z" U' I& r& |
::StretchBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),
3 k; r ]: P l4 W/ j- @hMemDC,0,0, mpBitmapInfo- >biWidth, mpBitmapInfo-
3 i% F. b. s# u>biHeight, SRCCOPY);
! q! g+ j8 L B) f# Z4 ?! T( T}
1 C+ f6 O T: I% L6 V // 结束显示真彩位图 5 q) K( r3 Y6 c9 J
: eleteObject(SelectObject(hMemDC,hBitmapOld)); K$ |! @1 l$ M; k; }
// 删 除 位 图
' \) e9 H) z$ L% B# a9 @8 u9 h l } else { : Z) d' ]* E% `6 `9 u( f2 I9 l6 }% C
' N- O# G( x: ?9 W0 v [& b1 v- A
// 使用视频函数显示位图
) g/ U7 c/ `0 n( s g" {6 D& u % p! P0 M, M1 U6 l- h$ t
if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() ))
9 |/ g% q5 {+ m6 `6 F! u2 umPos.x= mpBitmapInfo- >biWidth - mDispR.Width() ; " f+ J$ \- {4 g) x j8 O
if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height()))
1 Z* C# Y. o. x6 Q& YmPos.y= mpBitmapInfo- >biHeight- mDispR.Height(); & g4 i) Q( j& R
if( mPos.x < 0 ) mPos.x= 0;
: [8 J4 ]% ^& h' m B. v- J if( mPos.y < 0 ) mPos.y= 0;
& V, |1 }1 C$ @# n
) _% V* {8 o/ Y& I9 d3 L* R // 显示真彩位图
8 W! f; @/ D9 s) v/ {+ C# l2 ` DrawDibRealize( m_hDrawDib, dc.GetSafeHdc(), TRUE);
7 {" ^& C4 \5 c V* A( c# Y7 j ; r* s2 b1 r% c5 ^& t' e
if( mFullViewTog == 0) 1 K( I- R' d6 v) m8 M1 a3 C u
{ : y1 _# S) }" Y
Wid.x= mDispR.Width(); . i( {5 t& a* S/ T1 y
Wid.y= mDispR.Height(); t+ E1 e+ r! A' p1 E$ Z9 n
// 1:1 显示时, 不能大于图形大小 4 z5 `( R7 j( x% c! b
if( Wid.x > mpBitmapInfo- >biWidth )
0 T9 U/ C0 |) K3 i, C: {5 F( KWid.x = mpBitmapInfo- >biWidth;
* g: y: N& K% fif( Wid.y > mpBitmapInfo- >biHeight) & j' J( F# M* _8 ^/ ~
Wid.y = mpBitmapInfo- >biHeight;
& I, m# G9 X( w; J* k ( c2 S! l0 T p5 e! i
DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()
( H/ y6 E: J0 f) c& l( {" j, 0, 0, Wid.x, Wid.y, ' u5 z% L9 \2 K) k; y$ M7 B% [6 G
mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits), 8 P+ |* y" I$ \7 o6 k+ p4 b
mPos.x, mPos.y, Wid.x, Wid.y, DDF_BACKGROUNDPAL);
6 v7 C3 L' `6 q) \6 W$ E} else {
$ z% r9 n1 m: \4 Z6 d4 RDrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),
# b& k6 Z* y' T; q- f2 e2 n1 G0, 0, mDispR.Width(), mDispR.Height(), - n" j I6 e9 T9 m
mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),
) N# A, T. o. d+ I' ?0, 0, mpBitmapInfo- >biWidth, mpBitmapInfo- >biHeight, % N8 d: F- ]+ w$ K; k" L9 B
DDF_BACKGROUNDPAL); 8 V2 l( \8 {$ X) i. L! D
}
l4 N) D( C3 x6 U& F7 E }
7 b% f6 h" O& P- ~% O4 J# O6 p( y$ areturn;
* u. u9 v% r! d}
$ u6 g2 k+ B; ~7 ]4 G; A
5 x+ T7 F/ e) p3 @0 Y3 {% Y; M ' U& E! d" P1 K5 G
---- 五、使用CViewBimap类显示BMP位图 ! c7 X2 z! L+ F5 \5 q
---- 1. 在Visual C++5.0中新建一个名称为mymap工程文件,类型为MFC
! f# G! m; b) m0 X: l0 L4 N: jAppWizard[exe]。在编译运行通过后,在WorkSpace(如被关闭,用Alt_0打开)点
/ Q1 A# a; ^5 }- y# |& A- d: o击ResourceView,点击Menu左侧的+符号展开Menu条目,双击IDR_MAINFRAME条目
6 o4 ]) R+ u# k* H" ^7 c,进入菜单资源编辑,在'“查看(V)”下拉式菜单(英文版为View下拉式菜单)的 ( i: s& C' L- Q$ Z+ p5 K2 w$ J
尾部添加“ViewBitmap”条目,其ID为ID_VIEW_BITMAP。 2 E, T4 N- N: Y+ `+ P" e
# ?% k* U" X' X) u---- 2. 在Visual C++5.0中点击下拉式菜单Project- >Add To project-
' E) }) A* \# \. N- A>Files...,将Bitmap0.h和Bitmap0.cpp添加到工程文件中。
. b. m l2 Z4 |' C l* s9 u F) N& L3 d& N& a6 ]
---- 3. 在Visual C++5.0中按Ctrl_W进入MFC ClassWizard,选择类名称为 8 ?( }# a) G* x3 d l0 q# |
CMainFrame,ObjectIDs: ID_VIEW_BITMAP,Messages选择Command,然后点击Add ! p" f+ Z4 M$ D- d7 @) n; q3 H' Z
Fucction按钮,然后输入函数名为OnViewBimap。在添加OnViewBimap后,在 - g" O: V% Y; S* x; |
Member functions: 中点击OnViewBimap条目,点击Edit Code按钮编辑程序代码 3 @. U( K6 B) E' x- U
。代码如下:
# O+ l, _. X$ ~5 D* Z( c( i 8 |8 u* Q2 y$ r8 H. n
void CMainFrame::OnViewBitmap()
- I+ s" p$ Z* h4 z" c3 w* b{ 9 F7 s0 i% i) M- b7 |
// TOD Add your command handler code here 7 B8 z! e# Z# L
CViewBitmap *pViewBitmap= NULL;
( `: H! j7 Y9 V& `- s3 e: f
# `% q. {4 X/ Z4 opViewBitmap= new CViewBitmap( "BITMAP.BMP", this);
' D* C" ]7 A2 Z k& z! opViewBitmap- >ShowWindow( TRUE);
/ y5 q; I" i/ G+ P9 a2 I} " s% V1 p% X) ?; _! C; @) K/ G
+ E( g* ]/ P2 v# m; X9 h
; V: C9 \ r$ O: H( Y% @7 e; Q---- 并在该程序的头部添加#include "bitmap0.h",然后编译运行。
8 k2 @ E, }9 E0 e8 H8 F---- 4. 找一个大一点的真彩色的BMP位图,将它拷贝到BITMAP.BMP中。
" U8 V: [- ~& Y/ D$ J6 F' x1 `6 j 3 O3 H/ [7 v# z7 @" f3 s
---- 5. 运行时,点击下拉式菜单“查看(V)- >ViewBitmap”(英文版为View- > $ W4 }$ _- j$ i$ u8 a/ j- y
ViewBitmap)即可显示BITMAP.BMP位图。 6 I0 O7 i3 F2 d4 y) f; e6 v
, d6 `& H. N* Y& u
---- 六、CViewBimap类功能说明
2 k- G& F) W3 S2 L$ @' U3 c* v @ 6 Z: n9 `# U: v+ q
---- 1. 在客户区中带有水平和垂直滚动条。在位图大小大于显示客户区时,可 5 s, k( y! k# \- X# R @
以使用滚动条;在位图大小小于显示客户区或全屏显示时,滚动条无效。 & f+ l7 _8 [. n1 B. W* V
$ W" Y; Z7 ^( y, d' R$ V/ T" u---- 2. 在客户区中底部带有状态条。状态条中的第一格为位图信息,第二格为 4 T( r/ I3 g a% @5 C6 I7 W
位图显示方法,可以是使用普通函数或使用视频函数。在第二格区域内点击鼠标 ) P9 G2 M0 A* K* z: x5 W8 a8 ?, y! y
,可在两者之间接换。第三格为位图显示比例,可以是1;1显示或全屏显示。在 - I( P4 m9 j# u0 x, u6 w8 z
第三格区域内点击鼠标,可在两者之间接换。在全屏显示时,如果位图比客户区
4 y6 R' `( A9 D小,则对位图放大; 如果位图比客户区大,则对位图缩小。 6 X7 A2 ~7 Q1 e# w
" f$ k8 n5 k2 z6 A" h, G$ h1 l
---- 3. 支持文件拖放功能。可以从资源管理器中拖动一个位图文件到客户区, 6 l9 H% m' v; e4 Z C& S
就可以显示该位图。 ! a C& w, w$ N* y; p1 ]
# S/ \) J/ q% B9 a1 P& ~
---- 程序调试通过后,可以找一个较大的真彩色位图或调整客户区比位图小, : p! t- g( j: E# M2 E! @5 G
0 @+ f1 V* V- o- D! g
在全屏显示方式下,比较使用普通函数与使用视频函数的差别。可以看出,位图
$ c8 j w5 }$ J: M$ [; t8 m放大时两者差别不大,但在位图缩小时,两者差别明显; 使用视频函数时位图失
1 i2 Y L o: ?6 E真小,显示速度快。
5 v+ c: _3 j- K, F7 U + E y( f7 p, Z1 U
---- 还可以从控制面板中将屏幕显示方式从真彩色显示模式切换到256色显示模 ; r6 a5 {: X3 ^1 @5 `: S
式,再比较使用普通函数与使用视频函数显示同一个真彩色位图的差别。现在可
" Y6 ?/ n, K8 K" \1 d以体会到使用视频函数的优越性了吧。
& n5 M* w& b, \/ G
; ?/ D4 X; o" c, T---- 在全屏显示时,位图的xy方向比例不相同,如要保持相同比例,可在显示
+ @ h: x; c3 ]/ p5 W) A9 P; l1 R程序中加以适当调整即可,读者可自行完成。 |