QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3766|回复: 0
打印 上一主题 下一主题

BMP位图文件结构及平滑缩放

[复制链接]
字体大小: 正常 放大
韩冰        

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

跳转到指定楼层
1#
发表于 2005-1-26 12:42 |只看该作者 |倒序浏览
|招呼Ta 关注Ta

3 W* y6 R" J0 N* ^

西安交通大学流体机械研究所

" k) t* E% d7 g

张义云

' _4 H, X$ s: n

' s3 y# ?( `- o. }2 D1 Q2 K

---- 用普通方法显示BMP位图,占内存大,速度慢,在图形缩小时,失真严重,

8 Z; b. W) K0 E$ y( ^

在低颜色位数的设备上显示高颜色位数的图形图形时失真大。本文采用视频函数

$ Q6 ~5 C$ T' b! ^

显示BMP位图,可以消除以上的缺点。

7 ^$ X5 M" }+ I2 y1 g

0 |7 M( k( }2 h2 Y8 u2 S

---- 一、BMP文件结构

; ]& @7 b3 `2 ~0 D& Z

4 @! m1 y& S2 Q2 Q3 k' y. l4 q# X

---- 1. BMP文件组成

4 s7 C: c7 C* W

- X9 G/ E2 R) ~3 l

---- BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。

+ ^1 b, `7 O& P7 V$ G; p

* B. h( H3 V# a8 s* W* y

---- 2. BMP文件头

! F! H8 f$ n$ Y/ `! j* z

; J- J* x: w X7 A& e

---- BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息

! l$ H3 r; C( f% M

。

4 k1 \# ~' W, E

2 ~5 a; c# [7 b6 W$ Y5 Z

---- 其结构定义如下:

# x8 h& y! b' X, R

( L% l7 b% V, t5 w. ]( s; z. R% u

typedef struct tagBITMAPFILEHEADER

+ G% I! P# H- c( l

{

- y4 _3 R' f9 ^" w: ?2 p

WORDbfType; // 位图文件的类型,必须为BM

( Z% z+ h3 I( H* u6 m& a

DWORD bfSize; // 位图文件的大小,以字节为单位

2 A+ h- V4 d0 B$ K+ ]( [- l- c7 }; D3 r, C

WORDbfReserved1; // 位图文件保留字,必须为0

h: q, t& N+ ]

WORDbfReserved2; // 位图文件保留字,必须为0

' u4 w" @: p3 c+ q

DWORD bfOffBits; // 位图数据的起始位置,以相对于位图

3 j4 Q9 z; y _* x" b

// 文件头的偏移量表示,以字节为单位

: V6 J1 _5 E7 X9 \: G6 V( Q. I4 G

} BITMAPFILEHEADER;

' O- [: _1 q" P3 ^4 I

5 j/ F2 I$ Q8 S# k# |' j

9 Q8 W+ S8 @5 K$ e. b6 U& v% o

---- 3. 位图信息头

2 X/ @; w/ _* k: p+ ]& p7 X. K

----

1 h ]8 l' ~ l, c. ?& d* d% O

/ N0 a) o# U4 ]5 }" E. x

BMP位图信息头数据用于说明位图的尺寸等信息。

" V! y3 O/ @, x( _

typedef struct tagBITMAPINFOHEADER{

1 s' e9 |7 n! A: P

DWORD biSize; // 本结构所占用字节数

1 S! \) p- g# X2 r. _, s* G

LONGbiWidth; // 位图的宽度,以像素为单位

! y9 U2 w U- v

LONGbiHeight; // 位图的高度,以像素为单位

5 Y8 {4 W0 s# G

WORD biPlanes; // 目标设备的级别,必须为1

! ]- z6 ]9 Y5 j, ~, y

WORD biBitCount// 每个像素所需的位数,必须是1(双色),

% M2 f, {9 b. k P

// 4(16色),8(256色)或24(真彩色)之一

9 W: l' j! G. [- C

DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),

( g! ?( ~! U5 k4 l

// 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一

! l K( ~: Q, q+ R4 U# L V

DWORD biSizeImage; // 位图的大小,以字节为单位

1 o v0 |6 Z1 T5 i8 L

LONGbiXPelsPerMeter; // 位图水平分辨率,每米像素数

6 v* L& L) S @( c/ M, Y7 L2 k

LONGbiYPelsPerMeter; // 位图垂直分辨率,每米像素数

/ C# ~: X& o/ I5 \0 I: g

DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数

6 |7 t) X) |: n

DWORD biClrImportant;// 位图显示过程中重要的颜色数

! T- }0 }0 L3 d* L2 V' ~

} BITMAPINFOHEADER;

8 o9 O+ z c; |/ D& M& }

8 n( e( I' i: ^

( E# ~ ]( x% S+ z) \) p

---- 4. 颜色表

3 g! S. `, G- \8 Q9 H! D1 ?

---- 颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个

. _# \8 n+ n3 }, w* w, v

RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:

5 Z/ C9 | n ?

" E+ B& ]' E2 ^+ M

typedef struct tagRGBQUAD {

: n+ e0 @; R6 b2 M7 L; y

BYTErgbBlue;// 蓝色的亮度(值范围为0-255)

( @3 g1 O9 }. D; o9 l: ~* t

BYTErgbGreen; // 绿色的亮度(值范围为0-255)

" F+ \+ y% ~5 D# S& t" Q

BYTErgbRed; // 红色的亮度(值范围为0-255)

* \# b3 k+ s' \8 O3 j- X

BYTErgbReserved;// 保留,必须为0

0 g" I' f9 V2 j. w' I* G" k

} RGBQUAD;

]3 E, S: K% Y

颜色表中RGBQUAD结构数据的个数有biBitCount来确定:

: k7 O7 M! \" V

当biBitCount=1,4,8时,分别有2,16,256个表项;

3 l6 ^2 B+ r2 ~6 ]

当biBitCount=24时,没有颜色表项。

- k% U' C* @- g

位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:

9 Q" U+ h1 ~+ L" `- S- z; x

typedef struct tagBITMAPINFO {

+ w9 ], |& J( s! I9 L) a' B

BITMAPINFOHEADER bmiHeader; // 位图信息头

% ~3 ]* o2 k% a2 L e2 M8 {# c' P

RGBQUAD bmiColors[1]; // 颜色表

9 w: h, I: P6 M$ P! d

} BITMAPINFO;

- c1 T. a u; g' J- @; E- ^* N f

* G- _& P" j& O$ Z1 I

% C" L ^$ }( F! f- Q2 k% F

5 i* @1 h4 y* \3 b0 M4 y2 C

---- 5. 位图数据

; |3 P" H$ S9 k7 j2 h4 P4 O

---- 位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右

4 p; O1 O4 `, `

,扫描行之间是从下到上。位图的一个像素值所占的字节数:

7 c0 a% A, a. E: E2 D% S

2 h5 y& `# B* ?6 i& w# k& |7 W v9 a

当biBitCount=1时,8个像素占1个字节;

% ~4 S3 f$ i7 c m! O1 N5 Y

当biBitCount=4时,2个像素占1个字节;

% s( e$ y# w% t. k" ]& R- F

当biBitCount=8时,1个像素占1个字节;

) }8 N) [7 |% o* s( `

当biBitCount=24时,1个像素占3个字节;

, B; j$ R4 V v* t' R5 ]

Windows规定一个扫描行所占的字节数必须是

$ q9 H7 o2 \. R% Q& P9 H" h( u( Z

4的倍数(即以long为单位),不足的以0填充,

[5 a2 V! V) I0 e$ n6 X) `

一个扫描行所占的字节数计算方法:

1 R* y0 |& N* [. l+ `: p5 u1 J6 `

DataSizePerLine= (biWidth* biBitCount+31)/8;

. H8 O/ {; r T7 K2 r9 W

// 一个扫描行所占的字节数

) r2 c7 i& u+ W/ ]4 b& x

DataSizePerLine= DataSizePerLine/4*4; // 字节数必须是4的倍数

/ s( Q8 J# h2 e& ]. w" B: B6 `

位图数据的大小(不压缩情况下):

; `) a6 Q r& M# ?

DataSize= DataSizePerLine* biHeight;

. e9 B% W# W/ D: T4 V7 z( R4 \

, }* v {, R8 |+ C

1 v. O4 e5 e' ]. N: Y( b

---- 二、BMP位图一般显示方法

5 ]3 N' Y7 y/ e- Y% I

---- 1. 申请内存空间用于存放位图文件

% l& J3 D b4 t! K5 e

' X4 `8 L( N& S! o

---- GlobalAlloc(GHND,FileLength);

7 q4 k2 h; b h2 z/ N

7 |7 [8 S0 ^# J2 I: X

---- 2. 位图文件读入所申请内存空间中

6 V( }/ L! u1 v# P/ G

6 g9 O8 j; G' l9 a

---- LoadFileToMemory( mpBitsSrc,mFileName);

e# \: g/ a, S4 D3 v+ w

$ k2 W- n& A8 }6 @6 ]0 c! g

---- 3. 在OnPaint等函数中用创建显示用位图

+ P+ D: F; S1 z2 c: d* c

- P L) W' H8 w, ~! y4 o

---- 用CreateDIBitmap()创建显示用位图,用CreateCompatibleDC()创建兼容

6 n8 _0 j1 a z e

DC,

4 n8 v7 n$ {# r1 S" v! z; G

) o. C4 t% `% c) [

---- 用SelectBitmap()选择显示位图。

7 h0 l5 e2 r* M' }1 G! |! P8 }

( ~8 a# h7 n' V# D& J `

---- 4. 用BitBlt或StretchBlt等函数显示位图

9 d# ?' r/ z* {* Y$ t" `+ \3 F

* Y6 D9 K. W2 A8 d$ g0 y

---- 5. 用DeleteObject()删除所创建的位图

! ]# o3 f+ u, t' A1 E5 H

6 y; T+ \6 f( G2 ?- {( S

---- 以上方法的缺点是: 1)显示速度慢; 2) 内存占用大; 3) 位图在缩小显示

9 u' |& i; A, V& O

时图形失真大,(可通过安装字体平滑软件来解决); 4) 在低颜色位数的设备上(

- M' o9 @5 v+ _1 E7 r }

如256显示模式)显示高颜色位数的图形(如真彩色)图形失真严重。

: P6 D& w& b$ U( q

6 p0 d. g- T* W

---- 三、BMP位图缩放显示

% H% I( S5 Z# ?7 U8 d3 O' T

( S$ ]! S1 a* f0 y, w

---- 用DrawDib视频函数来显示位图,内存占用少,速度快,而且还可以对图形

- z: L0 r1 M) W }/ Z( K0 Z

进行淡化(Dithering)处理。淡化处理是一种图形算法,可以用来在一个支持比

6 w8 a9 H" Q+ ?6 ~6 t

图像所用颜色要少的设备上显示彩色图像。BMP位图显示方法如下:

* j! q+ Y, q- W

$ Y( B% K% M- l7 ^( E3 _' }* v

---- 1. 打开视频函数DrawDibOpen(),一般放在在构造函数中

* E% {' \' H6 z0 u2 P7 S

9 E/ ]5 b* [" s# M

---- 2. 申请内存空间用于存放位图文件

3 l+ @6 p6 s2 q, z

7 f% U: w) U1 z% w

---- GlobalAlloc(GHND,FileLength);

" ]* }/ Q0 g6 `! {$ L

1 T# N6 `0 z ]# I3 ~5 N

---- 3. 位图文件读入所申请内存空间中

8 O' E1 D4 C; ~

- \0 [8 d# b" b; H

---- LoadFileToMemory( mpBitsSrc,mFileName);

( {6 B, f* ~# ], g7 R6 p' `' O

: S1 Q# e. M) G; m" J- B

---- 4. 在OnPaint等函数中用DrawDibRealize(),DrawDibDraw()显示位图

, \0 n3 |" ^) y

6 f- r5 q7 V% U0 S( T) `4 r$ }# l

---- 5. 关闭视频函数DrawDibClose(),一般放在在析构函数中

0 ?* l* O9 L' L- F

( F a! I$ {9 p

---- 以上方法的优点是: 1)显示速度快; 2) 内存占用少; 3) 缩放显示时图形

# e" Z9 m* A/ ^1 J! w# D0 j. p

失真小,4) 在低颜色位数的设备上显示高颜色位数的图形图形时失真小; 5) 通

5 j; D: I R9 J/ z& f7 ]$ |- n

过直接处理位图数据,可以制作简单动画。

! b$ ]; z2 G6 q6 P/ N! L1 w8 p6 Q: ^4 L

* X% I( H V8 d9 W: F3 i# a

---- 四、CViewBimap类编程要点

$ C* l/ v# a& k. T6 |, d2 s; d0 @. ^

1 P; T* u. x5 ]- q* d" S$ n9 g- l

---- 1. 在CViewBimap类中添加视频函数等成员

) z. ^. I" g3 s

0 ]# S# D/ S" C7 G5 _

HDRAWDIB m_hDrawDib; // 视频函数

4 W3 j f0 u3 ~1 |: W7 q% T0 ]

HANDLEmhBitsSrc; // 位图文件句柄(内存)

) T5 B+ `5 g( s# G" `

LPSTR mpBitsSrc; // 位图文件地址(内存)

. Q5 c e5 d* Q F+ v$ ]. j; ~

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

0 v- u; }8 h* j/ d4 Y6 Y

5 \; S5 f) K! V) q

4 z v; S0 k; X$ f

---- 2. 在CViewBimap类构造函数中添加打开视频函数

; q& s* T* s2 ~- n' t- N

---- m_hDrawDib= DrawDibOpen();

: w8 _& q8 I9 v

Z% A9 f: n3 j) o

---- 3. 在CViewBimap类析构函数中添加关闭视频函数

6 k. s* H! K, H [* n9 ?

# J' a$ T# ]4 |; r, Y9 i4 D

if( m_hDrawDib != NULL)

x5 n9 v- b- M; [

{

/ A7 ^- i, [' a* k! Q% K

DrawDibClose( m_hDrawDib);

- e. c, K/ z% [5 B$ [, g' n3 _

m_hDrawDib = NULL;

, v8 w( d2 L: [1 V5 }! s

}

- E O. E2 A5 m% Q) Z

: n% @9 Q g2 @5 F

$ x9 }8 g$ C! a; L! O, E

---- 4. 在CViewBimap类图形显示函数OnPaint中添加GraphicDraw()

( w8 e' F' m% R" C/ e3 o

voidCViewBitmap::OnPaint()

# S( M3 |: s$ D. e1 O9 K. k

{

2 ?8 T- f, I" O0 }

CPaintDC dc(this); // device context for painting

# E2 m5 C4 y7 A2 z" t

GraphicDraw( );

. U0 q3 V) y; a8 k! V# X3 ~) w

}

! _0 f/ T Y/ |& T/ Z& j

% G8 m8 v6 E+ g1 ^( t" c$ k

voidCViewBitmap::GraphicDraw( void )

( K$ Q2 b' `4 r9 Y% r

{

! M4 n9 x. Q; U0 a5 M

CClientDC dc(this); // device context for painting

9 ]" _* H, M) }. l/ X& M4 e" ~

BITMAPFILEHEADER *pBitmapFileHeader;

8 [' {) h6 g. e2 n- q/ A

ULONG bfoffBits= 0;

# e/ O: c2 H- C5 s3 N

CPoint Wid;

$ |0 u5 U7 g9 u

' P( p1 I/ H' ~' D; ~+ W

// 图形文件名有效 (=0 BMP)

" B4 h! t/ ~) D/ c

if( mBitmapFileType < ID_BITMAP_BMP ) return;

8 M* u3 A% _! u* i0 z6 x

: \: f- c% @) D0 G* b: l

// 图形文件名有效 (=0 BMP)

5 c. L# y/ ^; P8 o8 L8 L# p! T, f

// 准备显示真彩位图

5 h+ ~, x8 r4 w- L0 ]6 }' O q) K

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

( \' S) ]. _% t

bfoffBits= pBitmapFileHeader->bfOffBits;

$ ~& y, g# W- [8 `( k1 a- \# i

$ r8 k8 D# k4 J: U( K1 Q2 [7 f

// 使用普通函数显示位图

6 @3 f# M$ W0 a; ~" f) }# ]

4 p1 ^3 w% P! K2 H' L) v5 V) |# q; j

if( m_hDrawDib == NULL || mDispMethod == 0)

& ]- w& \, A/ B

{

) S @ l6 e2 p) k9 @1 U: r

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

) M+ i9 |$ R/ H

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

% g, S" T2 g! L

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

) |; A1 G$ y( ^8 ]6 t

// 建立位图

# L' g. Z6 y$ n+ M5 w5 ~

HDC hMemDC=::CreateCompatibleDC(dc.m_hDC);// 建立内存

' L, S- c0 W9 c+ g& E8 Q+ F" }3 F

HBITMAP hBitmapOld= SelectBitmap(hMemDC, hBitmap); // 选择对象

6 j$ F& Z3 H' S' a; g

// 成员CRect mDispR用于指示图形显示区域的大小.

( {# j3 V( x: j9 x4 l0 W, N

// 成员CPoint mPos用于指示图形显示起始位置坐标.

6 I. i% w2 i/ r4 A$ [1 ]

if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() ))

( E, X+ Q% D" C3 R8 j$ t$ O

mPos.x= mpBitmapInfo->biWidth - mDispR.Width() ;

3 ?; P9 T0 j7 b' I

if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height()))

) q5 W/ p! h& P5 S! c* c. }

mPos.y= mpBitmapInfo- >biHeight- mDispR.Height();

- v4 T: ^+ t6 y

if( mPos.x < 0 ) mPos.x= 0;

3 V4 E$ f8 s9 l% a% w: h

if( mPos.y < 0 ) mPos.y= 0;

5 S2 \- c; e. i# ^2 I

8 P/ P4 K1 \5 ~4 F9 m

if( mFullViewTog == 0)

p" e% b! e, X4 b: {

{

! Z* Y# t4 o, F0 z1 a

// 显示真彩位图

. A0 ^* ^4 q3 }' G! h9 H: \0 x; `

::BitBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),

' W4 Q; J+ h# v+ v

hMemDC,mPos.x,mPos.y, SRCCOPY);

3 ~# m- e. g5 W9 u

} else {

" n* t1 y7 h& n2 a

::StretchBlt(dc.m_hDC,0,0, mDispR.Width(), mDispR.Height(),

; G9 ]' m& J8 i* J! t/ p

hMemDC,0,0, mpBitmapInfo- >biWidth, mpBitmapInfo-

- [! U- Q5 _) H1 I0 U. K+ d- j. u7 s

>biHeight, SRCCOPY);

5 \/ x. w% O- J# g& M) u

}

9 q9 ~/ s( P$ ^/ L0 z- z; O+ @" Y+ c

// 结束显示真彩位图

7 k% z* j s7 R* V: O

:eleteObject(SelectObject(hMemDC,hBitmapOld));

7 |% w# y7 I3 L* ~6 \

// 删 除 位 图

" w: t i+ e) s

} else {

# e$ b* ^/ r# ^( K: ` v+ |

. @- t, w# A E

// 使用视频函数显示位图

$ j) t Z" E# k6 r: E/ o& r% ^* {

- M* ~' Q4 n' M) M; x$ \& k

if( mPos.x > (mpBitmapInfo- >biWidth - mDispR.Width() ))

) [0 B; W# P, `0 T

mPos.x= mpBitmapInfo- >biWidth - mDispR.Width() ;

Q& e$ N, u! S) c) }! u6 G

if( mPos.y > (mpBitmapInfo- >biHeight- mDispR.Height()))

k" f8 d4 w5 P" w6 j3 ^

mPos.y= mpBitmapInfo- >biHeight- mDispR.Height();

$ l* R5 U! B; j0 E

if( mPos.x < 0 ) mPos.x= 0;

6 I$ |4 J; w# |8 t% r3 x, s- A

if( mPos.y < 0 ) mPos.y= 0;

/ K; s$ |* d# |! B' y/ I& j7 B

5 q k2 x# u. g$ P; i3 G# {& x

// 显示真彩位图

3 ?: _( A% b' `, {- s. q2 _

DrawDibRealize( m_hDrawDib, dc.GetSafeHdc(), TRUE);

9 d; d* Y0 h+ j1 \* f

. `6 j' F2 @1 P' m( e% r

if( mFullViewTog == 0)

' t" ?6 v. V+ ^0 K7 \

{

p3 r f5 v1 A

Wid.x= mDispR.Width();

+ Z& s( y8 j5 v' r/ M

Wid.y= mDispR.Height();

# ^4 E- [. I9 K1 n! m9 S

// 1:1 显示时, 不能大于图形大小

8 m! n& o. R, E4 ~- J4 w

if( Wid.x > mpBitmapInfo- >biWidth )

. z( U& y7 q" i4 \3 ^

Wid.x = mpBitmapInfo- >biWidth;

3 D- M1 |! Q* r$ \& _) I# _" C

if( Wid.y > mpBitmapInfo- >biHeight)

6 J" G0 n4 k9 x' ?% b3 S; p- M5 z6 B

Wid.y = mpBitmapInfo- >biHeight;

/ ?7 q8 m/ S% `% L+ M( ^

: U, o9 M; r! L+ V$ q; Q

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

$ M4 V) }' {4 I& M% [

, 0, 0, Wid.x, Wid.y,

) \, ]; g1 g( Y D. e. C" {

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

G0 K9 u y9 l' b' t3 D

mPos.x, mPos.y, Wid.x, Wid.y, DDF_BACKGROUNDPAL);

: ]5 Q( e4 R% k7 D' m; c/ n- u

} else {

2 d! ?% R* I' d& U$ g

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

* X' D8 \+ m" h, P6 Y U

0, 0, mDispR.Width(), mDispR.Height(),

- H# _8 u' Y! D+ a) e

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

9 }; g! _- r0 v( k8 b' j

0, 0, mpBitmapInfo- >biWidth, mpBitmapInfo- >biHeight,

! I2 N; y* C; H) o

DDF_BACKGROUNDPAL);

+ o9 W9 Z5 c! l$ r6 o) ?

}

- {7 g& [% x+ a. G8 g4 M& }5 w

}

+ U& }. g5 s- i" m/ }

return;

1 r L8 s. A( L4 ~' I

}

2 s2 O1 @- j7 }2 i+ Z- m

8 e3 K# V! F4 ^( W, U. s

9 y. T% Y# H0 A

---- 五、使用CViewBimap类显示BMP位图

5 d3 F* ~( F: L$ x2 k3 b

---- 1. 在Visual C++5.0中新建一个名称为mymap工程文件,类型为MFC

& P% H, _0 s8 o8 {7 a3 N5 s

AppWizard[exe]。在编译运行通过后,在WorkSpace(如被关闭,用Alt_0打开)点

+ L0 v: M( \. ?

击ResourceView,点击Menu左侧的+符号展开Menu条目,双击IDR_MAINFRAME条目

* H7 y! W8 A( L( c, t: a

,进入菜单资源编辑,在'“查看(V)”下拉式菜单(英文版为View下拉式菜单)的

* q D* k- L T4 s+ k

尾部添加“ViewBitmap”条目,其ID为ID_VIEW_BITMAP。

( j* P. U, G1 Z o! f5 S1 q

+ R' C: u3 O! V

---- 2. 在Visual C++5.0中点击下拉式菜单Project- >Add To project-

1 P9 w8 v. V4 O' m

>Files...,将Bitmap0.h和Bitmap0.cpp添加到工程文件中。

7 o' h8 t+ o3 z. c6 ?: f

! G& E& G% m' T# Y

---- 3. 在Visual C++5.0中按Ctrl_W进入MFC ClassWizard,选择类名称为

. v+ |9 p) C. V9 l

CMainFrame,ObjectIDs: ID_VIEW_BITMAP,Messages选择Command,然后点击Add

8 K$ H7 U7 ^% U7 B/ y, d

Fucction按钮,然后输入函数名为OnViewBimap。在添加OnViewBimap后,在

6 J! `9 v1 X' q& V9 n, g

Member functions: 中点击OnViewBimap条目,点击Edit Code按钮编辑程序代码

( w! n$ m F# N

。代码如下:

8 H4 O: M; v9 a; A; |! N9 Y

0 R4 L6 {# G2 y% U; }! P6 h B( p

void CMainFrame::OnViewBitmap()

' p, {; I0 a+ Z! I

{

9 l5 V" g7 Q* D; ? b: D6 {

// TOD Add your command handler code here

) K$ @8 J# ^1 x6 A% u

CViewBitmap *pViewBitmap= NULL;

; j# H' P) t" ^8 q' W

3 d, Z1 s; `' X& r

pViewBitmap= new CViewBitmap( "BITMAP.BMP", this);

* d8 d K0 y( U; e% V/ f

pViewBitmap- >ShowWindow( TRUE);

4 \3 w9 Q- C2 K

}

. j( B* o* @" h

. y8 P9 R5 H& W' W( h" D/ R

9 ?( [- L5 {4 ~7 ?- u. ]& w

---- 并在该程序的头部添加#include "bitmap0.h",然后编译运行。

1 ]) Z% \2 q" [0 B: v

---- 4. 找一个大一点的真彩色的BMP位图,将它拷贝到BITMAP.BMP中。

1 C3 r7 s. v* w! E5 M4 }% E

( z+ d8 O+ K; w! a* k, V) G

---- 5. 运行时,点击下拉式菜单“查看(V)- >ViewBitmap”(英文版为View- >

! @" q: l1 l1 |, \- k! m1 ~

ViewBitmap)即可显示BITMAP.BMP位图。

0 q5 {8 H/ A7 z/ V7 T. h2 p6 _$ |

/ k5 l( E# {& G* ]- q

---- 六、CViewBimap类功能说明

$ r& [- k0 Z" U/ W

% J: p; `4 I3 z" ?+ _: i: p2 E

---- 1. 在客户区中带有水平和垂直滚动条。在位图大小大于显示客户区时,可

( m; G+ n0 u7 F4 y

以使用滚动条;在位图大小小于显示客户区或全屏显示时,滚动条无效。

8 O8 I4 L' r. ~9 s7 B6 L6 k7 {' @

3 j: W& q3 Z$ p2 V

---- 2. 在客户区中底部带有状态条。状态条中的第一格为位图信息,第二格为

$ f' h% R/ }& A) M6 ~, g, f/ R

位图显示方法,可以是使用普通函数或使用视频函数。在第二格区域内点击鼠标

4 P3 t0 j' [9 l4 O" Y% ^# l

,可在两者之间接换。第三格为位图显示比例,可以是1;1显示或全屏显示。在

$ F! S3 W5 Q' H

第三格区域内点击鼠标,可在两者之间接换。在全屏显示时,如果位图比客户区

5 ^# v% `( W1 q4 Y0 j) t

小,则对位图放大; 如果位图比客户区大,则对位图缩小。

! q3 `0 A: x- M8 v) |) r! I- r1 N

. S6 y Z$ Q: N2 e

---- 3. 支持文件拖放功能。可以从资源管理器中拖动一个位图文件到客户区,

- t' C {% S2 S G ?; M

就可以显示该位图。

6 ~( O3 A$ z6 j% `

; y& T6 N; ~3 O9 t. d6 f# {$ I

---- 程序调试通过后,可以找一个较大的真彩色位图或调整客户区比位图小,

# _0 K; w# D" I) ? 7 B6 o) C" S* H+ x1 \

在全屏显示方式下,比较使用普通函数与使用视频函数的差别。可以看出,位图

$ C* }) h1 [; R+ X. R& B3 ?

放大时两者差别不大,但在位图缩小时,两者差别明显; 使用视频函数时位图失

3 k1 x5 ]9 A; g u* Q% [

真小,显示速度快。

& e1 a8 O. ?& z

. |; m& W/ U/ @( m

---- 还可以从控制面板中将屏幕显示方式从真彩色显示模式切换到256色显示模

' N. Z' ~/ x/ M3 a: r3 l& n

式,再比较使用普通函数与使用视频函数显示同一个真彩色位图的差别。现在可

F1 u4 d4 h7 Z, D7 m

以体会到使用视频函数的优越性了吧。

: z( X; h% A; I) M R

# B) L+ n9 |3 I# v/ k

---- 在全屏显示时,位图的xy方向比例不相同,如要保持相同比例,可在显示

" b1 D0 {- h( H

程序中加以适当调整即可,读者可自行完成。

zan
转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
您需要登录后才可以回帖 登录 | 注册地址

qq
收缩
  • 电话咨询

  • 04714969085
fastpost

关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

手机版|Archiver| |繁體中文 手机客户端  

蒙公网安备 15010502000194号

Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

GMT+8, 2026-10-18 01:42 , Processed in 1.875548 second(s), 52 queries .

回顶部