|
3 P2 q0 O+ |2 T( ^' ^5 d- I. z6 V
西安交通大学流体机械研究所 f# n) T8 L0 B: B) M: e9 P/ `
张义云 3 \! P; ^# P$ z/ I
. b! ^- f6 x! s' e
---- 用普通方法显示BMP位图,占内存大,速度慢,在图形缩小时,失真严重, 0 B9 x# U- v# l( `5 G
在低颜色位数的设备上显示高颜色位数的图形图形时失真大。本文采用视频函数
7 G O: m/ t* T! K4 y" U显示BMP位图,可以消除以上的缺点。 : [7 R7 u* t/ M" [) v( d; \5 q
/ {4 B6 }. t' _! P5 ?, g* u: m8 O---- 一、BMP文件结构 1 a& M4 A) v( s: l% {
/ t* g+ e* i) A1 G- B- L
---- 1. BMP文件组成 7 e9 H% G( k4 }9 o4 m0 p
, Z" H% t: B" C# @" ~% H---- BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。
* B6 L8 B( W: f4 N3 P! E
g( H, e" G: ^1 G+ o# r+ {( U---- 2. BMP文件头
3 v! ?5 z2 x A% @( H* a
1 q; D/ F* Y E! [+ `3 w. E: e---- BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息
, Y8 e) {/ E8 [ _# \。
0 V# G* |' ^1 l9 z/ J 5 @- N% Z4 ?* Q
---- 其结构定义如下:
, |, t& G8 |: [; _3 M3 C8 H1 Q
" f' |, b2 i- |5 H$ }typedef struct tagBITMAPFILEHEADER , Q* F' s! ^- T7 X$ v5 q) M
{
7 _- Q' m! K' P9 ?/ h0 g& Y4 dWORDbfType; // 位图文件的类型,必须为BM , V2 U) t$ S" q' u+ H
DWORD bfSize; // 位图文件的大小,以字节为单位 7 C, C$ S/ ?- S
WORDbfReserved1; // 位图文件保留字,必须为0
& [* g3 T* M9 j. p7 E- r# DWORDbfReserved2; // 位图文件保留字,必须为0
4 _6 X" F6 H3 M6 E* yDWORD bfOffBits; // 位图数据的起始位置,以相对于位图 M4 q: R, u! p3 H8 o
// 文件头的偏移量表示,以字节为单位
6 r. d9 `* ~$ e" }# a6 \} BITMAPFILEHEADER; ! I3 u; s8 @3 M5 W
* A+ s2 f$ o: L" P8 P* j# B
2 {9 `2 L, t9 b, \' p( W" }; e \' C---- 3. 位图信息头 , L" R, Y: g v' M" w" |% A
---- 0 }9 F2 d. ~8 {
+ R, h- `+ h7 OBMP位图信息头数据用于说明位图的尺寸等信息。
, a( z5 ~& s1 E1 G" I" ]typedef struct tagBITMAPINFOHEADER{ Q' j6 B! F" a6 a4 h" b
DWORD biSize; // 本结构所占用字节数 0 a4 z2 c& U- R% q5 ^% t
LONGbiWidth; // 位图的宽度,以像素为单位 , x: |& F; C% l8 H& v) D2 J5 R
LONGbiHeight; // 位图的高度,以像素为单位 ' X3 J3 W9 |! s2 A8 T% D! D7 i
WORD biPlanes; // 目标设备的级别,必须为1 - F9 v' _& S* O2 p
WORD biBitCount// 每个像素所需的位数,必须是1(双色),
+ Z/ ?: s3 D4 `* S. K8 { // 4(16色),8(256色)或24(真彩色)之一 1 c( ?* M9 Y/ s/ c$ |3 c9 n, s
DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),
) K, o8 ]) E% q6 T. _4 b // 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一 : f+ d( i/ O3 A3 y
DWORD biSizeImage; // 位图的大小,以字节为单位 " C: @; _8 N& b4 W# Q
LONGbiXPelsPerMeter; // 位图水平分辨率,每米像素数 , m' m2 H- Z! h% y
LONGbiYPelsPerMeter; // 位图垂直分辨率,每米像素数
$ j& E" }# q1 B. f0 I- ] DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数
! p# v( @4 v. { DWORD biClrImportant;// 位图显示过程中重要的颜色数
" ?5 l( N. [% q' U; A0 X} BITMAPINFOHEADER; 2 s+ y. p6 K2 N$ \4 K
Q% c( x; p2 S
0 V/ x: C8 x: b [4 Z
---- 4. 颜色表
m7 G2 H0 V. Y( ?, J4 g---- 颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个
3 P0 A2 Z& A' |# O3 `& n4 JRGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下: / |- Y |8 j/ g( |9 N* X
6 U5 J1 C3 b: o! ttypedef struct tagRGBQUAD { / _: W) ?& a& d" z- }) O
BYTErgbBlue;// 蓝色的亮度(值范围为0-255)
* S1 B3 j' h* p8 E! o' RBYTErgbGreen; // 绿色的亮度(值范围为0-255) # D9 L$ `6 N, F7 c5 O; f
BYTErgbRed; // 红色的亮度(值范围为0-255)
3 z4 O% L% M* [. ~' h0 L5 |! |BYTErgbReserved;// 保留,必须为0 8 b+ Z# X; N8 H) e' N$ x# o% o
} RGBQUAD;
* E& o/ K# P; B. u颜色表中RGBQUAD结构数据的个数有biBitCount来确定: ' e4 E* t o% Z; H v i# ~- o
当biBitCount=1,4,8时,分别有2,16,256个表项; 9 |0 s: i. t3 D4 s3 a) a, i$ L
当biBitCount=24时,没有颜色表项。
. r% V9 ^7 x2 q9 S 位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下: 6 h: [; Q1 Y9 {6 O" X7 a- R Q
typedef struct tagBITMAPINFO {
0 M- ^! Y* i: f4 k: i( r8 m BITMAPINFOHEADER bmiHeader; // 位图信息头 ) `* s1 y$ N0 C+ r6 ]
RGBQUAD bmiColors[1]; // 颜色表 " j3 F2 Z' {6 e) Z) z$ R" j, g7 m
} BITMAPINFO;
" U! p! h' n! P9 Y U/ |6 l9 B
6 }# @9 ?" @: ]0 S1 R" u
( ` v' Y3 ]2 @8 D& M) z9 i: d ) j) B: X3 I* Z. J7 V
---- 5. 位图数据
. u7 w1 G4 y3 l2 T---- 位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右 # h; u3 k V( P7 N8 Y
,扫描行之间是从下到上。位图的一个像素值所占的字节数:
/ n0 [! r, Z- i* z 4 I1 ]% j1 X; ]! _( j
当biBitCount=1时,8个像素占1个字节; 7 [/ g$ C( P5 D' y0 z" n. E6 |' S
当biBitCount=4时,2个像素占1个字节; ; Z! `& N! N/ w
当biBitCount=8时,1个像素占1个字节; & `9 x0 _1 d4 d- f7 D0 b7 {
当biBitCount=24时,1个像素占3个字节; ; S6 i( C* l `0 u* ~/ q. A4 @
Windows规定一个扫描行所占的字节数必须是
0 m# W) W2 R* \6 z9 G1 G4的倍数(即以long为单位),不足的以0填充, % {" c: g+ g+ K9 A: U& H0 I8 M, V# i
一个扫描行所占的字节数计算方法: / C/ E. X9 D: x9 f1 n6 s' s3 c1 }" i0 Z
DataSizePerLine= (biWidth* biBitCount+31)/8; 0 {7 f+ ^/ Q; z( Y: Y/ }" X
// 一个扫描行所占的字节数
! }' y6 w+ B* S: j% c& JDataSizePerLine= DataSizePerLine/4*4; // 字节数必须是4的倍数 8 p# T& @7 o L2 }9 X( _8 ~/ j
位图数据的大小(不压缩情况下):
! H: B: d4 j1 D* t: S6 B& ?- FDataSize= DataSizePerLine* biHeight;
) c3 l& U# E& r) R3 a& r( s6 S $ W3 e9 v9 |% f8 _
9 ]$ X2 G- c% [& z& R---- 二、BMP位图一般显示方法
, @3 ?5 K) a! ~2 e9 X---- 1. 申请内存空间用于存放位图文件 1 p+ [) F0 p6 G, R, T& w. n+ T+ r
9 n( `7 M/ H; M/ V8 l6 Y---- GlobalAlloc(GHND,FileLength);
! E- i+ C9 p6 ?) q. C" m
* z `3 i3 d6 M0 l4 e9 P- l---- 2. 位图文件读入所申请内存空间中 $ J9 C' W) t5 C7 P
% |7 f9 g w' U---- LoadFileToMemory( mpBitsSrc,mFileName); - M" i( o. v/ x; _
& X A$ R! C! F! Z
---- 3. 在OnPaint等函数中用创建显示用位图
0 n& x& d! \3 X f* T' q
* j# _2 D" z& {) _; Z+ V---- 用CreateDIBitmap()创建显示用位图,用CreateCompatibleDC()创建兼容
$ ], O, Y! K }; e$ u* W3 ODC, : W3 [2 ]; P9 U# t" h2 n+ B4 C8 i
2 B, k. Z& N2 F5 q
---- 用SelectBitmap()选择显示位图。
* {. C4 e8 `& S$ i2 Z! `/ h ' s) }5 p4 {# p* m3 x/ I# u5 M7 O
---- 4. 用BitBlt或StretchBlt等函数显示位图 5 ~6 a/ m3 f% U# P" K' x
_" C9 `0 b2 W# @
---- 5. 用DeleteObject()删除所创建的位图 ( o0 X P, ~# c
( U" B' j7 R: F7 W/ c( v7 Q---- 以上方法的缺点是: 1)显示速度慢; 2) 内存占用大; 3) 位图在缩小显示 2 z. C% Z) f8 v0 j" F. s7 K6 |
时图形失真大,(可通过安装字体平滑软件来解决); 4) 在低颜色位数的设备上(
8 ]+ |% ^ l- e' E8 n' d# I如256显示模式)显示高颜色位数的图形(如真彩色)图形失真严重。 " s) B. V/ R; x& S8 n4 @9 ~
$ K' [7 ?2 q, Q- y' |- W: x& S0 s
---- 三、BMP位图缩放显示
$ p( J/ J( A% Y9 X4 {- e
- f. F+ p; n0 h7 S# Q7 s---- 用DrawDib视频函数来显示位图,内存占用少,速度快,而且还可以对图形
. O8 I% d' F, [- o8 ?6 R/ e; }进行淡化(Dithering)处理。淡化处理是一种图形算法,可以用来在一个支持比
9 Q9 @4 Z: j) e0 z' u: Z图像所用颜色要少的设备上显示彩色图像。BMP位图显示方法如下:
- K2 ^+ ]# x9 v* a |4 {, I
! M3 [/ Z; \2 L" {---- 1. 打开视频函数DrawDibOpen(),一般放在在构造函数中 Y0 G9 y' `% V( _7 I% l0 V5 ^+ x
6 E) T; X: N/ Q7 q
---- 2. 申请内存空间用于存放位图文件
# d' t8 O6 k# X F: U, y , B B' d4 y; }2 E. c: o
---- GlobalAlloc(GHND,FileLength); - _- U+ j* W2 a& C4 }8 \9 ?
; ]- q, f+ J7 n# [2 A2 ^
---- 3. 位图文件读入所申请内存空间中
! ^4 f! H4 ~. T9 N/ Y0 N. `
4 [6 ^( C Y% S& R, ^. i* X---- LoadFileToMemory( mpBitsSrc,mFileName);
4 `9 \: a7 [2 v& v5 i V' p! f M6 M' M* P& s# n; w
---- 4. 在OnPaint等函数中用DrawDibRealize(),DrawDibDraw()显示位图 # p' s( m; n! ?+ Q* _; \
' F, O" e' V; ?3 E0 G1 ?/ O& ?---- 5. 关闭视频函数DrawDibClose(),一般放在在析构函数中
( q$ I5 v2 i6 \+ d2 Z8 M8 c : V; t4 b5 ^( n* J, l& @
---- 以上方法的优点是: 1)显示速度快; 2) 内存占用少; 3) 缩放显示时图形 9 ^- T9 a V5 p X0 t- A
失真小,4) 在低颜色位数的设备上显示高颜色位数的图形图形时失真小; 5) 通
3 p0 e8 a* H% C过直接处理位图数据,可以制作简单动画。 0 R w+ k A% N7 b5 v
1 P s; H7 Y3 M2 \---- 四、CViewBimap类编程要点
6 I9 d7 s1 Q. s' `$ X' i
* P1 i9 D( u S. h( d---- 1. 在CViewBimap类中添加视频函数等成员 ! l( O0 }; a# I$ _- \% w% N
8 w2 n: S! T4 K8 O6 R
HDRAWDIB m_hDrawDib; // 视频函数 4 C- _# s& E3 x7 X
HANDLEmhBitsSrc; // 位图文件句柄(内存) s' {1 a4 U1 ~- j
LPSTR mpBitsSrc; // 位图文件地址(内存) - h/ W/ A2 j7 c" U' K
BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头
d; R a. k3 k+ ?* m0 Y! M# ?
( U( \. Z6 G ]. g) Z: ^ 9 O9 f, t/ f/ y0 G- D, y; \
---- 2. 在CViewBimap类构造函数中添加打开视频函数
4 L# O' `$ D- h) y$ q---- m_hDrawDib= DrawDibOpen();
' [8 r1 S; r& o! \& {/ v ! V+ x8 w* V/ Z+ X9 f% l* P
---- 3. 在CViewBimap类析构函数中添加关闭视频函数
" A1 u8 ~; m* ^* f5 q% W % `3 w( D) W3 g- N. Q% ^0 c9 _
if( m_hDrawDib != NULL)
! [, i' e# P4 p5 }+ Z0 p {
5 X2 j; z/ w# |' E, |% D/ Z* B DrawDibClose( m_hDrawDib); / S; q3 N5 }- z8 r( i, g
m_hDrawDib = NULL; 8 {# Y* P( V+ a" T0 T- g+ i( G4 z% p
}
% d* z( ^% ^) m3 R4 W6 f6 F
( z' q5 N, b' x# u
* q) o9 O- Y" h; i5 B---- 4. 在CViewBimap类图形显示函数OnPaint中添加GraphicDraw() 6 y: J4 l/ \; @. |: V
voidCViewBitmap::OnPaint()
9 J, O: k6 `5 v{
& Y4 e/ p$ ~3 I9 O: eCPaintDC dc(this); // device context for painting * h7 a+ |& s# A! V, O2 a
GraphicDraw( ); C7 [+ a+ o3 h# U
}
" K. ]# z" L1 x% n. b6 Q & o6 N6 d3 m% Z# T6 K" K" w
voidCViewBitmap::GraphicDraw( void ) - i/ M" |+ B1 h% E0 L
{ 4 s# G4 r/ x* p% N7 h/ d: k
CClientDC dc(this); // device context for painting / q7 C" i/ e% O. b1 P @" _) e, v
BITMAPFILEHEADER *pBitmapFileHeader;
, K: X* T9 N; R' v+ ]7 {ULONG bfoffBits= 0; - o$ Y# K! y3 F
CPoint Wid; + l% n! u4 I+ U0 E' n+ x
: {8 c" y# L3 _8 q; L// 图形文件名有效 (=0 BMP)
+ G* Q. C: {1 m, U! Sif( mBitmapFileType < ID_BITMAP_BMP ) return;
3 j% c `% s, w7 j- F( b ?, k R$ h3 g+ v; j- E2 Q* k( W
// 图形文件名有效 (=0 BMP)
" f7 G' M) Y- a5 ~: z" }4 B5 I" D// 准备显示真彩位图 2 [3 ~, D7 e. a$ W' l' Z
pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc; 0 P: V5 H3 _0 g4 [! M
bfoffBits= pBitmapFileHeader->bfOffBits;
3 O) D* F2 S6 w" `4 r
: ~+ b9 Y% A: Y" ]) v8 o& L2 ~// 使用普通函数显示位图 , M" ^: R1 }7 ?$ h. a& g
6 v s: G4 Z7 S: S% H- @- lif( m_hDrawDib == NULL || mDispMethod == 0) : F8 E( ^1 f5 c J* R
{ W N; l0 b. ^$ p- q0 j
HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC, + a( X' o- p, ?5 {% O
mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits, # z1 Q1 I- N n
(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);
2 \* i+ c0 y$ z# }// 建立位图 3 M& B# J/ R! J; A) v$ L5 u
HDC hMemDC=::CreateCompatibleDC(dc.m_hDC);// 建立内存 0 G/ e# q8 n3 s+ m. j# }9 u; W
HBITMAP hBitmapOld= SelectBitmap(hMemDC, hBitmap); // 选择对象 3 T8 x9 N) o& p: Q
// 成员CRect mDispR用于指示图形显示区域的大小. + t# y, h4 O3 n) m, y
// 成员CPoint mPos用于指示图形显示起始位置坐标. 3 \% d2 r* B# N {/ ^
if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() )) 3 k; Z0 M4 T8 E( m& `0 w0 x
mPos.x= mpBitmapInfo->biWidth - mDispR.Width() ; ! z2 \0 D& `+ i% b1 Z
if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height())) ; Q3 Y/ _6 ^9 t+ Q2 w
mPos.y= mpBitmapInfo- >biHeight- mDispR.Height(); ' L5 V ~+ [! I9 V* U" E$ e. n l
if( mPos.x < 0 ) mPos.x= 0;
0 n0 A" t( |' j if( mPos.y < 0 ) mPos.y= 0; % v# D: T7 N& z! w0 l1 L1 ~5 I! [
( w* |8 H0 W: `+ n% B' j$ d$ N
if( mFullViewTog == 0) 9 _8 d2 b: b; x* c) X% ^
{
" W. N! O4 L9 t! Q) n6 }5 R* n// 显示真彩位图 * x; |. K9 i) z1 N% E- Q3 P' E
::BitBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(), # m2 ?/ a0 m, u0 E* S0 a
hMemDC,mPos.x,mPos.y, SRCCOPY); ; a) @: b! P5 T: D+ |1 L& c
} else {
' ?# h* `/ Z% k$ B: |7 I) Y% J::StretchBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(), . f) e2 }7 y+ G4 W! A8 l
hMemDC,0,0, mpBitmapInfo- >biWidth, mpBitmapInfo-
{ _" C) Y' |2 \& ?>biHeight, SRCCOPY);
- B# T' o& B" B' `} $ E8 [& V. o4 z
// 结束显示真彩位图
; V9 Z6 ^- u- }5 s0 S, A- I5 X : eleteObject(SelectObject(hMemDC,hBitmapOld));
! x. ^- r: k' S+ l" Y// 删 除 位 图
$ d4 k# P3 p" P* F! m [ } else {
7 C) J6 V0 a4 p# a9 e, ?* F- N1 {6 G5 i
# @( e& x0 I% h; J5 X% f // 使用视频函数显示位图 " G5 c7 f" m. q* h. ~. J/ f& F) r
/ f/ M# m5 z' O0 _5 Y; A5 p if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() )) . g, k* i6 o2 l( \1 L; n* i
mPos.x= mpBitmapInfo- >biWidth - mDispR.Width() ; - \5 l# `6 }% X& X
if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height()))
% J! X% |8 `( [, n! p: V# q; cmPos.y= mpBitmapInfo- >biHeight- mDispR.Height();
- F7 s8 J$ g! e8 {9 j6 ^ if( mPos.x < 0 ) mPos.x= 0; & h+ `+ ?, N1 o9 p
if( mPos.y < 0 ) mPos.y= 0; : S' Q4 D% k! g: D$ \. T
4 N- Y2 K, }9 V+ z0 @. { // 显示真彩位图 9 b9 u" P3 H ?" L5 v2 b
DrawDibRealize( m_hDrawDib, dc.GetSafeHdc(), TRUE);
3 u0 T ]$ B0 F9 r6 {7 f! x' Z 3 m$ l$ K2 z$ N7 ?1 l
if( mFullViewTog == 0)
6 B3 n* x& r% r p{ ( j, M) m2 k; C1 t' Z/ j1 M* D
Wid.x= mDispR.Width(); ; J3 X3 h7 Y' C) C) s, d; {# s4 E, j
Wid.y= mDispR.Height(); 3 _/ q. S* w0 b6 `$ z! d j0 L5 e% A: v5 [
// 1:1 显示时, 不能大于图形大小
& y6 a4 f' t$ |# f8 v4 ?$ G2 x! F! Zif( Wid.x > mpBitmapInfo- >biWidth )
% C- z6 _6 X/ n* H9 ^$ r! A. iWid.x = mpBitmapInfo- >biWidth; 9 j$ C5 _' Q+ n- E8 I6 V* I' o A
if( Wid.y > mpBitmapInfo- >biHeight) $ v& S/ ^% _* ?: D8 \
Wid.y = mpBitmapInfo- >biHeight;
% y3 O6 K* s6 H; B / Z" E+ X W# T& M% d- z
DrawDibDraw( m_hDrawDib, dc.GetSafeHdc() 4 _8 A$ ^+ [1 J5 I3 Y1 i2 K
, 0, 0, Wid.x, Wid.y,
7 M7 Z8 j" \3 F* x) b2 p" a: ]mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits), + t5 R$ h' @' h& e; J5 R
mPos.x, mPos.y, Wid.x, Wid.y, DDF_BACKGROUNDPAL);
' C/ [$ D# {* E" R8 w7 f5 J6 @} else {
& g9 d. k' ~. N* F3 r4 n, E2 iDrawDibDraw( m_hDrawDib, dc.GetSafeHdc(), + w( z# N* |2 ~7 B$ ]1 f+ W
0, 0, mDispR.Width(), mDispR.Height(),
6 {' [0 B/ a: n+ ^mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits), 1 l/ ^- z$ c. X" b0 J: c1 _
0, 0, mpBitmapInfo- >biWidth, mpBitmapInfo- >biHeight, ; S3 G4 l- Q3 A! Y6 A- r
DDF_BACKGROUNDPAL);
5 l2 ]" j1 ?0 [3 i* R0 R} 1 M0 |! x& B: P, B1 A
} " a8 L. r- d/ M$ v5 P9 g
return; . S" J+ V! ^, C/ O
} - e1 i% Z0 }. `8 B5 p: I7 g
% I3 H0 q/ p% k o; V1 s! G
0 k& L; }' x, r4 Y1 o
---- 五、使用CViewBimap类显示BMP位图
4 t' b6 x- v6 w4 W2 }% g- `---- 1. 在Visual C++5.0中新建一个名称为mymap工程文件,类型为MFC
; k# [# N; z$ zAppWizard[exe]。在编译运行通过后,在WorkSpace(如被关闭,用Alt_0打开)点
- g1 b# R1 k+ C2 d$ E# p击ResourceView,点击Menu左侧的+符号展开Menu条目,双击IDR_MAINFRAME条目
" K+ g4 d) l: v! ^$ |* ~6 r# T: K2 n1 Y,进入菜单资源编辑,在'“查看(V)”下拉式菜单(英文版为View下拉式菜单)的 # U$ [9 q5 i" w1 {" D% r: a
尾部添加“ViewBitmap”条目,其ID为ID_VIEW_BITMAP。 / f% u1 u# m: `- k6 b" a
& P" J; Y0 J7 M/ U% O5 p5 s0 s9 P---- 2. 在Visual C++5.0中点击下拉式菜单Project- >Add To project-
9 y# E/ F) h* d! [ k# [>Files...,将Bitmap0.h和Bitmap0.cpp添加到工程文件中。
1 O' D) X2 X! P0 x+ _+ t" `
- A4 u3 ?5 W/ @7 Q# m---- 3. 在Visual C++5.0中按Ctrl_W进入MFC ClassWizard,选择类名称为
0 `: B+ p$ R6 { r8 m0 h: ^( |. I4 Z# _CMainFrame,ObjectIDs: ID_VIEW_BITMAP,Messages选择Command,然后点击Add 2 [5 F8 |0 X9 b( _( A D2 _
Fucction按钮,然后输入函数名为OnViewBimap。在添加OnViewBimap后,在 & P. U* k8 ^; p# E
Member functions: 中点击OnViewBimap条目,点击Edit Code按钮编辑程序代码
6 ^- U' G d r" t。代码如下:
0 v9 r, N u3 R
$ S r( w! q# @% f! Xvoid CMainFrame::OnViewBitmap()
& Y6 f/ Z+ y" N4 g{ , B: F3 D# f( D+ ^/ U" n
// TOD Add your command handler code here
9 U v5 a7 K# o. u9 C1 a' |' FCViewBitmap *pViewBitmap= NULL;
/ L& t: O9 t6 y& o5 G) O$ S3 S 0 j8 O; Z4 u8 j( p, u; W: _/ c
pViewBitmap= new CViewBitmap( "BITMAP.BMP", this); $ x3 j$ g- K. i
pViewBitmap- >ShowWindow( TRUE); 8 F/ O1 l' {. s9 G y! ~- |
} 6 {2 h0 g5 }- k1 W" j" O6 F6 E
1 j/ b( o8 o- ]
& w5 Y3 Q Y3 }4 b2 U
---- 并在该程序的头部添加#include "bitmap0.h",然后编译运行。
! l$ F! l7 G/ z9 {" J---- 4. 找一个大一点的真彩色的BMP位图,将它拷贝到BITMAP.BMP中。
* ^) U6 ^) ^. f1 i, x2 S. v4 N% o
9 C2 ^: q( H8 q# O1 g- |5 r+ m; @---- 5. 运行时,点击下拉式菜单“查看(V)- >ViewBitmap”(英文版为View- > - D: L1 G, O- Y0 R/ P) B
ViewBitmap)即可显示BITMAP.BMP位图。 2 ^5 E$ |6 F- o- g& R' R
! K9 r5 ~6 O/ D' y---- 六、CViewBimap类功能说明
2 W) E5 Q. N+ j6 f6 o3 X. g4 _/ n 5 s/ Y- z; w, R% f: g
---- 1. 在客户区中带有水平和垂直滚动条。在位图大小大于显示客户区时,可 5 s' Q1 p5 x4 t2 q0 u
以使用滚动条;在位图大小小于显示客户区或全屏显示时,滚动条无效。 % g& ]- g& l3 w2 A5 u6 a
) ?8 }3 w7 p8 r& D) Q" g
---- 2. 在客户区中底部带有状态条。状态条中的第一格为位图信息,第二格为 $ K% {% ]; [6 _' j( a" Z/ x9 E
位图显示方法,可以是使用普通函数或使用视频函数。在第二格区域内点击鼠标 1 i, ~4 M- K- @! _' A, ?: E- C
,可在两者之间接换。第三格为位图显示比例,可以是1;1显示或全屏显示。在
& q" j- m$ ]# X0 G7 d# @: d$ \& L第三格区域内点击鼠标,可在两者之间接换。在全屏显示时,如果位图比客户区
! a& r- J6 }, D$ i, ?5 [小,则对位图放大; 如果位图比客户区大,则对位图缩小。 $ _) L1 P! w4 h8 ^0 ^3 C6 I$ q- q
! f0 |2 Q* `4 U$ {* @+ B/ X
---- 3. 支持文件拖放功能。可以从资源管理器中拖动一个位图文件到客户区,
5 V8 ~8 `! ^% Z5 c3 L就可以显示该位图。
) \" j2 x& A' T 7 x6 u3 B5 {6 k0 g+ O8 p( i2 K/ {, k
---- 程序调试通过后,可以找一个较大的真彩色位图或调整客户区比位图小,
6 u; Y6 H$ b8 C
! m# q2 _$ g8 [( C在全屏显示方式下,比较使用普通函数与使用视频函数的差别。可以看出,位图
, p M: [% K- a放大时两者差别不大,但在位图缩小时,两者差别明显; 使用视频函数时位图失 9 j* j3 `) u$ I8 }
真小,显示速度快。 ( B9 Q `& J8 m2 S1 C2 T7 L" F
; u/ @: m; z2 a: Z
---- 还可以从控制面板中将屏幕显示方式从真彩色显示模式切换到256色显示模 1 l( f/ `! R& g4 x/ U
式,再比较使用普通函数与使用视频函数显示同一个真彩色位图的差别。现在可
( g& G' c' w3 A% T( Y+ j以体会到使用视频函数的优越性了吧。 / K: u0 v7 f- I
* h" I+ i( h- f9 ?
---- 在全屏显示时,位图的xy方向比例不相同,如要保持相同比例,可在显示 / j2 N5 J. H3 m6 m8 _
程序中加以适当调整即可,读者可自行完成。 |