QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

$ ]3 T- u3 _, j1 w

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

7 B7 L C6 i9 M3 W; }4 I- R

张义云

1 J8 v* f/ m( Q, i

9 I* H- G9 K( a1 [; F9 m [/ k! ?

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

. t, i/ G: z% P* P. q

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

T" `8 J* D! m: u9 }4 T% u* l

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

: b G; {5 N4 `9 ?+ W* L

5 U$ q2 _. R6 s C; H* R4 }+ D

---- 一、BMP文件结构

( L1 y8 F5 m# c

0 I8 q1 u% S3 m

---- 1. BMP文件组成

/ S: f& i# o* d8 P/ H

) t) |2 H( `# f0 _( X# Z. O7 W

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

* k& l/ ^ K* p+ l- q$ { ?

) ?$ r4 @ o( l

---- 2. BMP文件头

" D# v7 b( z/ `3 V# v" V4 p+ Z

0 }: \6 {! b7 Q; M6 d

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

+ O- s0 c$ s2 N" Y9 d

0 v) x+ z, @' u3 n G3 N6 `2 b; h5 R" p

8 w- A( W/ E- i

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

7 z5 C0 F& ]) q" Q5 m

$ e& ~) w! ~$ s( f' T7 C: V8 E

typedef struct tagBITMAPFILEHEADER

7 {' H9 g$ g& M

{

, n% v3 R- @2 {2 a* |9 e

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

2 K7 k7 l$ d/ c; {

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

3 U& d0 q, z/ G. L

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

M" C5 L4 O( Q

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

7 `7 y: ?% O/ k$ ?

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

5 `2 V4 m, k3 I. K j* A- Y- g

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

5 h, D( L) G8 n) ^

} BITMAPFILEHEADER;

( y1 l4 D" ~" G, `

% W, ~4 ]: g4 G! j- _0 X0 D

7 `( C, o1 `$ c& `% e2 S

---- 3. 位图信息头

8 a: Y C# h9 B4 a7 [8 A& \/ b

----

$ I1 g8 \* g6 ?5 ?+ _6 n8 _6 S) m1 ?

+ u; w0 Q' S% W6 k' q1 t

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

8 z& N& |8 u# Z' p8 ?

typedef struct tagBITMAPINFOHEADER{

s2 @9 [: R3 L# @

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

. h4 j1 N: i% x+ n' ~! M) v% P& p

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

& @/ t0 d+ j) o

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

; r- P+ k" q# k) Z, N7 `; i X

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

' B1 \* ?% I) x

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

. |- X# X9 w! \% ^8 F

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

. A; F7 M l4 T* v' t

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

! z2 t3 O0 e" o; s5 a) h$ W; }

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

: s" N! [, ? f4 ]

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

( o' V E$ B+ N8 X! @' a' w4 T i

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

+ j7 P1 d4 f) S& e2 Y8 i& y+ q

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

7 L6 p4 R3 W9 {5 z2 p

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

- s2 H% F; C) W2 Q y2 ?

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

! G/ g7 Y% l, [) I4 k. R' N6 |

} BITMAPINFOHEADER;

1 l3 I3 Y: [& X5 A$ A' f% S3 c5 \) f

' `6 N- J+ O& }9 O

4 L. d" B0 P& y6 q

---- 4. 颜色表

, l" |$ M9 }! |/ v+ Z$ [

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

! C% z% Z m% M2 ]" U

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

. n. A' l, }$ ?& y8 ?

3 a3 i% N$ R0 r

typedef struct tagRGBQUAD {

9 j0 i3 V2 ^4 }7 V) j

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

4 g r" |7 } P6 [1 ?

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

9 W0 d- p/ X# t9 f6 E

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

( @" {- C# p3 \3 k# q

BYTErgbReserved;// 保留,必须为0

# }" @. l0 V1 O% M& {

} RGBQUAD;

7 M }' J9 I2 s! S% Q4 J

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

8 x( y1 e' s' }! c, s

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

% v! I+ h# ?. C/ c: d" x# {

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

4 ]$ v6 o( F, c& N2 h

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

D R2 I. x, b5 C. V

typedef struct tagBITMAPINFO {

0 t( n+ @$ ]/ [$ \4 d( l

BITMAPINFOHEADER bmiHeader; // 位图信息头

/ ]+ n' ?0 H+ d( V* H6 _

RGBQUAD bmiColors[1]; // 颜色表

8 `1 d5 o K5 x

} BITMAPINFO;

; T+ T+ ~$ `8 X" N# h2 w4 G

, Z4 l) q Z# ?* C

' T( z/ j$ h9 Y

3 i8 y# S1 s' ?+ A

---- 5. 位图数据

! D2 F7 m$ j9 {& c- m" e

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

# ]+ }5 d3 d4 J2 d7 C* L

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

3 h4 X; @& a7 Q0 q5 ~; X/ I9 `% n

! T$ N1 E' |( k# b/ p. j

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

: h/ F$ ?- Q% M- X9 A4 `

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

. A! ^. z* q. T. i$ k$ V2 ^

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

, @, q0 l! r" \

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

: { M- M3 M# V) q: J$ n0 L! }; h2 P

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

3 H4 v( x8 a6 d0 I* H. ]6 _* ]& O

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

, U3 x0 d0 O! y5 m

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

( o6 l# a h; ~& Q2 t" y

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

4 O; H2 I7 }! [2 A. E, Y

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

4 l2 ?9 x+ `8 i3 c! c/ x/ R7 I2 y

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

( A5 i: ~* \5 W" a+ O

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

* J0 Z4 @( X) g! J# X

DataSize= DataSizePerLine* biHeight;

, G2 j5 l: P1 ^( W! |

`, V3 g) @$ t4 |6 V

' H6 [1 @6 f X+ T8 f

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

r; R0 J# X$ T: m3 b8 H+ W9 W

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

# d, V% F; v5 {0 Y. C6 W

, t T% `* N8 E

---- GlobalAlloc(GHND,FileLength);

. U' l$ L- ~8 T7 ^; ?8 d3 C, F

4 V' E& V( B6 v( p

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

8 ]: \% t% t+ d* t, R& y) V/ K

1 d& r D" a4 A \" A! U$ v

---- LoadFileToMemory( mpBitsSrc,mFileName);

% D/ _+ q% R' R( v! Q

: X( \( t( `' | l, w, ^2 D

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

6 A, N V* x; V

! Y0 i5 r! V( d

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

" C: [8 D( ~2 ^& k/ l6 |

DC,

; w6 Z5 M/ w! D9 u

* k0 `: p1 |9 {# k

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

: C5 X+ }" ]; w% p; f9 g

! V* T p1 r! J" c1 g' W6 L% v( z

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

( W; m$ d$ T6 D

/ W9 b: n/ b$ T1 F6 ?8 _0 D& \

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

; Q( Z: k% K2 l* a

m3 T5 Q# o0 t; i1 W

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

1 M( m4 l q9 o, p

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

0 e4 q/ m. Z5 v9 j$ z; A

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

% g, r5 A3 j- L) y9 B

n' P3 ?' H8 c K

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

% v! f1 J: A% A3 y/ a g

. A! Y. e q& }3 i" A# h2 g* h: y

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

5 A$ Y7 e* ?: ?3 I" }( D$ x

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

& V# G4 q6 H3 E4 f( f. r! Z

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

+ u, e0 N4 m+ b W

/ n U& p. o& z' ?+ g( Z4 e

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

0 }" [. {/ I. p* L1 W- {

. S& V; _' K4 @7 A! g$ e1 N( {

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

% `5 L. p8 t4 H& G7 ^* W+ q

e1 a/ C& ?3 |* x4 `+ a2 ]

---- GlobalAlloc(GHND,FileLength);

+ y/ w' m- [3 _' | Z- B( R+ A+ }7 z' E- _

/ _ c/ F E, j9 V1 ~! u# t

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

6 j2 S3 u" w5 P/ b1 |9 O6 H

( k! d8 p# m$ P( E+ {* Z/ p m

---- LoadFileToMemory( mpBitsSrc,mFileName);

, q4 d& w& s S! |/ J$ g- a

& s) a, |; E$ b3 O" A" P* a

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

. j1 a) q. o# M, p$ U) P

6 Y; N( n0 T. ]. \

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

5 W* d2 G+ n& Z2 S& `; w0 X8 P, O2 T

* H! k# z4 } z1 B8 I' [

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

. A. j, T! N3 q4 {

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

( H1 ~, J6 R H1 J' V

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

, I2 l ^. c& |4 R- x+ e: H

* }- U$ S" X3 \6 m$ w

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

& Q1 P* z8 J6 x1 ?. _

. b1 P% N9 B( r/ E: q; X9 {

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

: e& r9 i+ R/ F8 z* M

* X; z1 ~- G" Q+ G/ P: x9 u; H

HDRAWDIB m_hDrawDib; // 视频函数

* l: L- ]& ]+ W

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

% \. C1 ^0 j5 E" o: `

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

& z6 m' P& L' U4 J

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

8 R. `1 N5 o) W# G5 |

* ]% D/ ]: `, D9 {$ f9 ~

c$ E+ K q! ?" _2 V

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

! h( }+ @( D$ o( ^7 J/ w

---- m_hDrawDib= DrawDibOpen();

. J. Z+ J+ g: U7 R" w

( R6 |# p4 }! K

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

; d" i9 |% s2 |: _+ w

" f6 U/ G3 Q' M. F8 R. L/ X: n, l

if( m_hDrawDib != NULL)

7 z: s# |! P6 U! S

{

. E# |% B$ r Z. n* e& s# `

DrawDibClose( m_hDrawDib);

/ o$ k7 C* w. l+ R5 Q; Q: W, Z

m_hDrawDib = NULL;

/ l) Y5 v3 ?' n) S" z; [

}

9 b3 O) \1 n# f

+ r( K( p0 l* I

! y/ h. X. P! s2 G6 [: b [# {3 C$ @

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

2 U, f$ Y. a9 c) m/ a

voidCViewBitmap::OnPaint()

- ^/ ]! B- w4 b

{

% ~: W' B3 ]0 _7 _/ m1 l9 l

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

' ?. V+ H2 L& R9 X7 M: d

GraphicDraw( );

0 z2 }& F$ _) K/ O, N3 o

}

* T7 s/ S# ~1 D6 O9 }3 m/ r( c

; k" L0 m) i- m1 {. X+ s

voidCViewBitmap::GraphicDraw( void )

9 R$ j- ~4 _' g4 k

{

; y0 g/ C7 ]1 {/ K9 w8 G+ y

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

( p0 k; d0 b1 U9 e& J* m/ L3 U

BITMAPFILEHEADER *pBitmapFileHeader;

+ r5 Y8 m) O, o4 A

ULONG bfoffBits= 0;

0 L% |# n" I" e" N8 F0 D; q

CPoint Wid;

5 s! N! ?+ e3 S' H. ?2 M! S

' T7 f: y1 Q4 d- S: [' t( \

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

+ f, A' V8 E( u5 f1 W% x" y

if( mBitmapFileType < ID_BITMAP_BMP ) return;

: c" U9 X9 c' G8 r

9 G5 s) z8 a, Q& d5 [# |

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

@# ^$ o+ f. C1 D( ^/ @! Y

// 准备显示真彩位图

( h7 q- G) g( w9 v0 @# ]4 W

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

, B4 [ E6 ^) u( t& y2 A M

bfoffBits= pBitmapFileHeader->bfOffBits;

! Q l0 r) E' K. P) T$ f

/ A: q; L. a1 Q

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

( B3 B- H: f. S

% N% Y# V" y$ m2 h) M) T6 k0 O

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

5 k0 d5 s- y+ j/ d5 b5 `

{

2 @, Q1 w" ~7 C+ L9 e8 _- M, q

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

8 d% O, j& p/ l3 L, C

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

$ W' F* [. l) m' p, r# \

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

- }) ^0 b2 d" g U6 t

// 建立位图

8 h5 w+ [6 l2 B9 t k5 j* r

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

! H. H0 L9 a& J" o+ ~$ n+ G

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

9 F6 O9 I7 F9 z% B* B

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

$ G- z( q4 I8 v4 t2 g6 G( A

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

1 K' W7 V" h: b9 ?1 K# D" m5 i, [

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

. n. B9 ]5 u! A5 \! X+ U

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

2 J" x: i" q: T

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

, E/ S [' V: S+ R. r) J4 Z# O

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

$ l6 n; w% p% R! \) r% t

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

' |# |1 [/ @1 z& E' o9 a8 ]4 j' a

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

+ h' o# d, c0 w8 ?# E+ j# r5 K

5 H0 K9 _: k/ y, H7 ^' r4 v, D

if( mFullViewTog == 0)

' m3 Q1 l2 A( z- |% ^8 u7 C* F; [

{

0 d$ p% n* c) e3 i& {

// 显示真彩位图

4 ]& w n3 d+ y, Q2 Y1 K h

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

( Q2 G# ^ w! A& B7 T

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

1 W/ v( h, |: q# M$ n

} else {

! g/ }2 z3 D! c- \ v. ~% i4 s

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

" Y. i& }. i- {" W0 e6 C

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

. i7 d0 ~" ^$ f; z+ D( z" |

>biHeight, SRCCOPY);

) F3 @# P o( \% d

}

& Y6 G" o% ?9 t2 @! O, k

// 结束显示真彩位图

0 K. t s4 r/ e& k7 V8 r

:eleteObject(SelectObject(hMemDC,hBitmapOld));

" {" _( K/ E2 C( M6 r- U

// 删 除 位 图

7 f# }' b0 l( ?# ^2 J1 H

} else {

9 l) D( a. i" p# m% [' z

8 q( \; r1 ^0 d2 q! b; n: Z

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

& ]7 m' i" [% ~$ o' _# |

+ k/ D O/ J" h7 B7 P

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

- Q' D4 |! @8 y/ U! E" i8 W2 e

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

3 B& @+ }4 j- z( s3 h* E

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

. \$ k0 g& t( n# D5 H

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

) E" t' D! A0 F6 N

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

" d0 r6 B! D2 G4 i

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

" u& n$ Z' C$ Y; X* @

0 ~6 O! `# v' G) v2 L% n: X4 Q

// 显示真彩位图

* W* \: k! W; T: V, k' V

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

7 @3 I+ y' W" ]+ s% ]) F' T& Z

( B* G& o. m, D4 r

if( mFullViewTog == 0)

5 E0 C; ]' u& w, n

{

$ l0 _6 E% ` W* \, E/ A

Wid.x= mDispR.Width();

# z) t/ Z! W! X* e& k* T: x& E

Wid.y= mDispR.Height();

1 Z) p9 U- j9 I9 T

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

9 v/ @& [* B- X

if( Wid.x > mpBitmapInfo- >biWidth )

. i& q+ g) J% z0 q

Wid.x = mpBitmapInfo- >biWidth;

( a% D( H, L& m( j ? Z

if( Wid.y > mpBitmapInfo- >biHeight)

8 Z: t4 T7 H' c: R0 x

Wid.y = mpBitmapInfo- >biHeight;

# B) `6 P0 ]& }; u- B- q$ E1 g. I

$ e7 w6 |& Q) b( \' j" U: R

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

$ k5 J1 b: Z J8 v' w$ H) R; e

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

, x9 l7 |, c% t

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

% S( `' o, }, D* T0 n' ?7 |7 S

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

2 r7 C5 ?4 Y4 w; R0 [

} else {

. o1 ~" j; B+ n+ S: p, S2 F: j

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

- D) r- T0 P" U% ~# C& F" J

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

. @# @1 a" b6 V1 X5 D* K: J4 X$ Q9 x

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

( [( M* H( z7 z+ E$ ~" G% B

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

8 i0 _. t0 V6 I/ Y* p' l

DDF_BACKGROUNDPAL);

. }6 |& D1 z- {4 [

}

- A0 @1 ]7 c% e1 ~. o) o1 U6 v. D

}

1 ~ f# d& X7 B. o$ B! r

return;

" W; y" V( o- t! n& r) _

}

4 G& U! Q) d- ^$ q

6 F: E9 O# D8 n+ v5 H2 |

& P7 X( f0 f9 Q: d: {8 s

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

! ~6 l U1 R0 ]9 p) v

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

& F4 q/ M8 y) O

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

8 S2 t; E9 W B" Y

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

) } _6 W$ q1 Q' s0 }

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

3 \$ ]- G3 y! ^, K+ e2 X' F

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

0 u+ _! s; j0 i3 B+ L

. \2 }/ h% N7 ~3 ?) `6 ~

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

- r9 S4 S0 R. R" K: B9 f! Q8 j

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

" l9 t8 ~2 C0 y

' w+ {5 R6 X5 c+ C1 B

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

3 \) s+ `$ G% ?& a# |) |! W1 L

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

* ]. G/ y2 Y b. M( M% K1 O- O

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

4 @- y" c" ]- g4 d1 m- u

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

; ]# p: r4 T! G& f" A1 D8 \

。代码如下:

7 d5 ]1 {* w8 S; K3 D

( b ?' r0 ~2 }

void CMainFrame::OnViewBitmap()

& j; u6 e5 j2 \

{

' q+ O3 f1 r9 R7 R, n8 q7 j) |7 V8 c! u

// TOD Add your command handler code here

1 L% @: p, o/ }, M! ?7 j$ a7 w

CViewBitmap *pViewBitmap= NULL;

5 _) R i- J9 ~ D1 M

! n% A! |" X. d, R* Y

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

4 u, e: u+ W$ W# |& ?9 n

pViewBitmap- >ShowWindow( TRUE);

9 W7 L: N" Z2 Y$ Y5 w- r0 N, A+ `

}

" {# z" G |; p; h$ b

; b( Z$ n+ ^. X1 S3 `: _7 L

, l' |9 `% n) v0 g3 g

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

( q, Z6 Y8 T. C: Q& t" L6 M

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

7 p3 J9 X' L" f6 n1 {

2 U4 V5 s9 `+ c, c8 o2 k: }

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

# S, v+ j4 U. Z' b( S7 E

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

6 V' S1 V; z' R. [- U

[2 U0 n. ~$ f* u4 X' H+ W

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

% v* `, ^' t! I4 j

3 y& z. Z7 X8 [+ L' B* R. n% l

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

9 q: s& j, R4 W+ V

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

0 Q" [1 [4 K5 [6 c% V! m3 q

6 r1 M2 `% `1 t2 Z$ E' v' m

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

2 D3 x, i# p1 M' i# u& b: L9 G

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

6 T! G1 ?, q! d3 E, d+ e

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

4 J9 K/ L3 D( g" }" ?

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

: C2 n3 r, m2 W2 g0 ~8 ]% F

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

+ u* A: J( h" D% T$ y) h) d6 w) `9 D

P3 C! i+ t* X1 h2 u$ A) @! N

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

4 H* k' x# r& s

就可以显示该位图。

6 C* ]4 j4 N' Q6 L! F4 O

+ Z) I6 f! R4 O8 j: h/ {; b6 v

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

$ |, \, ~$ n/ P8 F 1 F3 F; L) [6 I! |: w5 Y0 R

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

( }3 S* z7 q+ Z+ L; _

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

8 P; K* N% B! ?& ~

真小,显示速度快。

3 m a( H& V3 |8 H# x! c

" f2 o. S3 P4 ~0 D

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

& `! J _! V" F; i

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

- v& Q6 Z* L- _# w: ^9 j

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

9 m& `' F: D8 ~7 _( I/ O" C7 L3 w

4 V8 G( Y7 z6 K& T

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

5 g; w. z) C4 m) f! i: u% b

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

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-4-18 10:47 , Processed in 0.387511 second(s), 52 queries .

回顶部