QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

0 K8 U* l7 d& n$ a% A

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

5 U; z+ J# v* Y! q0 Q. B

张义云

# H6 q; ^- a2 Z! x1 R

$ t+ K6 z2 J" y$ g5 P# e' X, P

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

4 z6 `: E! n4 F

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

6 T. E" y' `8 j1 J# ?) h

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

( Z1 c* n3 M3 J5 {# K

& M% c- _3 \, U# @1 v$ l" A

---- 一、BMP文件结构

6 V* V z) U4 F+ ?1 f$ w9 N

+ K0 _1 N; H( `) n% t

---- 1. BMP文件组成

; U4 X0 i- V1 R1 X$ c* T

) c( w) D' |& Z! B0 z

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

% ], _6 g2 G; J

3 B$ n6 q- `2 q& {: c; w4 n

---- 2. BMP文件头

, r4 i) n& O1 a: q e

, [ s: X1 D, O k9 e+ ]

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

' I$ J! z l; e8 y$ }

! N8 V5 t2 i; o5 g1 S

- v5 P" m/ T& d& [& d* T

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

: m+ j" \/ i5 o; r6 d; W

. G J3 u! q+ |# T9 o

typedef struct tagBITMAPFILEHEADER

- p6 I9 R: w# s6 a: k8 H

{

( ]+ I4 x* Y M) j2 z' J

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

`, u3 ~7 Z) B7 w+ X

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

2 c0 A, V* z! c1 V9 `

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

' i+ z4 ?# _ y5 _; V0 ?5 j1 |

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

9 V1 ]: V: E6 b0 `4 Y2 N2 s: G0 r

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

5 ^) h+ ~: [- ~, @

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

& Z& M, p3 H% F' T" J

} BITMAPFILEHEADER;

- M0 I5 N, N8 Y! X) J

0 Y$ d: g ^' a2 a1 s5 i5 f6 S

6 w, P: g S, d) B8 u. H: `/ i7 B

---- 3. 位图信息头

$ g( n" m9 T9 J

----

8 k( P' Z" U" O& p, `

2 t: `/ ?# [, J! z

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

% v. n) ^- H* T) b. ?: Q8 r

typedef struct tagBITMAPINFOHEADER{

! `5 u! ]6 M* M- }6 A* S

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

! N6 ~. F6 a( y' R8 S/ o7 t

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

5 P! g) C: K7 B/ R

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

% ^" f! [7 j: o2 L% w

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

z \9 d+ _& ~+ q

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

/ e- r& L# B/ N1 f

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

7 _$ ^& b% O+ t3 m' V

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

2 q! m8 W! W7 z& q0 L, g

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

' _' z" l7 z: H* M4 {$ G5 d

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

( I: C$ B5 y u/ g3 r- r5 `

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

9 n" K7 m0 V3 m( o

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

' n4 Y* D1 o T3 M# W

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

5 x- v6 m- W4 c% ]3 x9 `9 h9 [

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

$ a; l- H( E8 O+ \8 w3 c. N( l4 _

} BITMAPINFOHEADER;

, B$ B$ T7 P) p. _$ o

- s c; ] d5 W

' q3 f$ E ]2 f% |, Q% w

---- 4. 颜色表

- j2 I- Y! w( H0 t

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

0 y1 [; V0 F4 l" j( N; X0 \

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

) ~! ^: d/ C+ E) Q4 A

) t {) H4 z7 f( Y0 h

typedef struct tagRGBQUAD {

/ |' O* H# M! g: q

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

% z: T0 {/ @% S+ S

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

) c3 r0 t4 n b) d0 q

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

2 o; w/ D3 S2 `; @9 `

BYTErgbReserved;// 保留,必须为0

! d' S) B7 N5 `! {7 z& H

} RGBQUAD;

- Z. s: I4 c: p5 O

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

1 D* u$ T" c7 ]* U' C) C3 I

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

& L: R5 C; G% v. X2 H# @

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

9 o# n; {. u. R( }

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

3 ~. B7 b% Y, [

typedef struct tagBITMAPINFO {

" A5 w' f9 B% w: |, h

BITMAPINFOHEADER bmiHeader; // 位图信息头

0 `7 ^( ^, d0 \4 [" C$ I& z

RGBQUAD bmiColors[1]; // 颜色表

! `, k0 v8 y. ^2 Z3 y/ ]) n* h

} BITMAPINFO;

z' i1 W9 v2 S/ q7 G5 x% A

6 L8 M8 B9 M! X0 X. _

9 \6 [+ I$ y- Q: G5 _7 N

5 ~9 B, f4 H+ R6 O& x

---- 5. 位图数据

1 e+ D4 c1 H0 E' D8 `! h, x1 y) g

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

+ k; A8 f& f- l1 N6 B

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

6 }3 ?" Y% U! Q3 w! G

( D4 G# l6 J- d" l# ?4 U

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

& p* W9 \* p0 U5 K0 L5 w% J

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

0 F" e, B! o" _3 _

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

* a; a5 N: E. e, o! B) `) B9 W9 ~

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

& k/ e7 g) t; a/ I! `

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

0 J) m3 g/ p: C( U

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

4 @! A( \9 t- ~ i& d

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

) A! N% P! C* ~2 L; A. M

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

' c9 ? h6 [+ q+ ?4 i z' C1 i

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

# }4 k" h+ @9 ~. J, K6 y

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

p. v3 B. B q& l, W8 \( _+ w, ^

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

4 ~+ |. P E$ y! }+ Q) ~) S

DataSize= DataSizePerLine* biHeight;

, W$ O& Q4 @; R$ j$ U; e

4 e1 l. O/ u) X- E. w8 r6 T

) ^6 I! _( B/ Q& s: C( W& u! u

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

0 l; u9 D: J/ W7 r

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

8 [4 ?0 j4 `# Z- ] |$ l1 n3 j* f

7 C1 E# O- O( l3 K+ g

---- GlobalAlloc(GHND,FileLength);

5 t' y. x0 A( N! W0 ?# Q

C7 N/ D3 f3 m a

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

! [- k& k* w/ I5 T: J& I* s; U3 G

% w- N' b* F. b' i

---- LoadFileToMemory( mpBitsSrc,mFileName);

) T, G- j( \9 G! H& w

]+ X1 M, Y0 { V0 L0 @1 l

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

3 V( z; M- j* B5 P

& _# X" r! \$ r' J( {/ K

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

; i G) c: T7 q" ]2 R

DC,

0 d8 Q/ B& ]. y# i, E2 y' ^7 f

! a2 Q7 P2 J& R$ d

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

" l7 [5 G2 `! m3 [

3 i$ p0 r, G7 b/ v/ X

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

* O9 o" I- R4 t- T' @" r

0 t* }( ]6 O9 b

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

1 E8 L3 _# J2 I7 C; a4 l/ H) J

9 P6 B! h3 T7 O, l/ z: [( h

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

- j$ o8 [7 W* F9 k/ o: C( H

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

) N) C1 j4 ]! e3 l2 l8 v) k3 f

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

( \3 N$ t. c/ X9 v, L2 Y

; y: c! d2 m: [( O# ?! |, w/ L

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

* T) A6 X3 o: X3 b2 u. }; B

4 ~4 j/ t: a# c2 T# `( ~) z( f4 T

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

5 F' I" B8 C) \ G

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

- X6 q1 e O4 }" j

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

, G8 h# ?+ Q5 G7 M" c( t

: _( A7 Z$ i1 _$ D7 b( u w

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

' g2 [+ z& d8 E' T" G, U! h, ]

# H g" ^: ]$ }/ i- _, `

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

' r: {6 \% k, \$ L B7 q

5 l' A0 ^0 L# |6 n3 m

---- GlobalAlloc(GHND,FileLength);

& M9 F! i; X3 `) R! f2 {* |7 c

6 y9 ~' J$ N5 t& M$ ~, r2 Z2 Y: J! C7 L( C

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

5 q2 P6 m. e! @/ x, C

9 @% \1 w; Q/ `* F& `

---- LoadFileToMemory( mpBitsSrc,mFileName);

+ s5 b+ t2 Q6 o4 @

. p0 Y9 N1 ^! `

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

, B' u* X( }0 w& }, M' \7 f

9 l+ a% ?$ C0 \! G

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

) f( \8 [7 _/ @! D" ~

3 E! X1 D7 a5 K& t( U+ A2 }

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

. }7 y& m$ G( u) k% s3 P( ^

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

+ Y* T* X1 J( z7 _+ S! s4 [" g* m/ C. j

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

; Y2 c5 W/ y6 R" c, U

. v0 |9 ~* S/ g/ B4 v/ o3 q- x

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

1 G2 f$ S' y9 f2 k) W

J2 Q' y7 |# s3 t0 Q

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

' |0 s0 V A+ @9 g! G

; v$ N% X/ |: Q5 n3 @# C

HDRAWDIB m_hDrawDib; // 视频函数

+ _% X# r9 ^9 m

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

) g6 o+ \- X$ i% T" _" M

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

" [5 E8 b2 T3 |% `

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

/ V* c) q9 n. M2 u$ a

+ l3 \" y, w. T' I( M7 d

! e) z% t8 v" _# Q# }. E, W

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

6 ^' M9 U1 F l4 Z6 p

---- m_hDrawDib= DrawDibOpen();

7 Q W/ }, T+ s# A

$ q. j, D- q _! T' i$ b9 _! g5 `: x

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

! I0 P' P# Q9 c

# ?5 Z5 ~5 j1 A$ m$ Q* H

if( m_hDrawDib != NULL)

8 e! \- t* J! p% w

{

8 [5 T. l: O9 k' J) j2 y% E

DrawDibClose( m_hDrawDib);

* b% T" M) C- ^2 }$ G( C. W/ l9 n

m_hDrawDib = NULL;

: B: f; G1 ?! S! f7 S0 [# o

}

* {1 l# W" M" C1 p

0 b8 D/ v% ]+ T( p

! L$ G, T: m# a, z0 B

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

( k& f- x, Y" Z# x& z

voidCViewBitmap::OnPaint()

5 x$ g" _1 v* N/ N0 @7 V

{

. g, W/ i7 T m, c5 M5 @! ]3 ~8 i

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

6 s6 ]: w( V' _9 e" m

GraphicDraw( );

) @8 v( u, s( m+ e; r

}

( ?) |9 t5 B2 [# Z2 _5 J

- I4 ^( y# _: ~+ Q

voidCViewBitmap::GraphicDraw( void )

" _: _ m) I! u- Z+ Y( ?2 r

{

. y/ R9 q* L2 e: m

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

. u, t4 F6 l: z" P. b2 C

BITMAPFILEHEADER *pBitmapFileHeader;

/ a+ P- _% j' o

ULONG bfoffBits= 0;

5 ^9 ?0 `6 _4 B

CPoint Wid;

6 D, u# k2 S, }2 \ U7 r$ A

; @; H( W7 N ^6 _

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

0 G8 m3 @6 ^; G9 V- X. r

if( mBitmapFileType < ID_BITMAP_BMP ) return;

* t' z3 I3 n) f; Y

! n8 v2 M# j4 f- L- u5 s3 S; {

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

. c% A0 M1 d" G) x4 Y3 n- r

// 准备显示真彩位图

, }5 }8 U$ ^0 z+ ]% S4 w3 D

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

" j4 l- z' C! t N, X

bfoffBits= pBitmapFileHeader->bfOffBits;

( X2 z( n- f: G/ y

4 r% B1 L4 u2 Z* V4 w* j9 X

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

+ U1 t8 F' b3 N

: P- X2 j9 Q% _

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

1 {5 E+ `+ ^/ t0 D7 e% x5 A

{

/ d6 o9 h; Q7 E/ S8 }( `9 h

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

7 s a8 s/ \. W* s# L2 d

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

( J3 |) e& g- K0 }) _3 L

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

! M: Y- D) M# }

// 建立位图

- |: F/ P1 b5 k t/ S

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

0 }2 b1 Q5 T& E! o8 D4 r$ B

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

) f! O5 \# Z9 y4 E1 ~4 L# h

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

( L. j4 o- e( ~* f5 m U

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

$ m0 X4 ^; H1 \( k! I7 \3 h5 U

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

( |3 [: v( b9 `: b

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

- h. O- N, [$ A. Q7 t; S3 v8 o: F

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

* N2 S/ c" g7 Y, n* c1 p4 s# Q

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

* ^1 E( H) w' j

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

- P1 q1 T8 ?) q" [8 a5 H

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

1 L" ?1 i9 N; n8 p* u; l

4 ~& Z3 `2 n1 p" q6 o

if( mFullViewTog == 0)

. r+ R8 W, H" Q' U

{

7 Z: d) d; W/ |! H) d3 P+ Q

// 显示真彩位图

6 k5 C+ f2 M/ |6 [2 q

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

0 C) [" C6 K- j: h7 {# Y

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

0 W6 c6 ~' u- L5 o* I

} else {

: J+ j0 C5 p- D: ?" Y9 x' y

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

) T! z" g5 d$ b! a0 o

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

9 X0 F/ F6 J; w- u2 _1 Y

>biHeight, SRCCOPY);

( P3 k, J$ S( e+ ~. q* o! l

}

6 g! }6 a! _; ?+ M3 u' \

// 结束显示真彩位图

2 S. g9 I. G; z0 N6 U

:eleteObject(SelectObject(hMemDC,hBitmapOld));

, O2 j. a- [4 a- x' p7 l

// 删 除 位 图

/ _+ T* ^3 _# R$ {

} else {

+ [: S) s. d5 f

. E- ~: D4 Q5 Q/ F- r

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

0 v! M+ ]5 E! }6 [5 s

! K% S3 j5 V, }# l

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

" |( `2 N2 J+ n6 p1 U

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

$ w: h8 u B& g) c

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

P5 k; E" x2 p5 f" s

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

2 c' p- D, W% Q2 e

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

3 Z/ J7 m: ~0 _2 }/ t* d! J% [

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

J! s# f. A" Q( [9 V

9 N" q9 |1 w' S2 k9 n5 N

// 显示真彩位图

" L. K7 U# a+ d* o

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

# n/ J0 |, n! {& a! l

% q% i+ u: [1 Y

if( mFullViewTog == 0)

: y4 t5 b# I" |- R5 g( ^) g+ E# x% `

{

/ k7 F' z$ s8 g |& R. ]

Wid.x= mDispR.Width();

& T( v; V8 [! G7 f% b; t" }; [

Wid.y= mDispR.Height();

) J2 Q, ~$ ^. e' |5 v; q

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

- \2 }/ o: ~4 c; {

if( Wid.x > mpBitmapInfo- >biWidth )

3 t, R3 c- x+ U. A/ H

Wid.x = mpBitmapInfo- >biWidth;

+ r1 C4 a5 \. p9 ]' \. n8 g N' G

if( Wid.y > mpBitmapInfo- >biHeight)

9 T, m8 t! h; E/ w

Wid.y = mpBitmapInfo- >biHeight;

8 t1 d2 N3 I, p2 U0 y

) Z9 P. m/ B6 B s) i

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

$ Y7 D% k# K$ o" Y- |; h

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

* ^0 T, a/ S; ?% }

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

d. z. h7 O; j- b) S9 P

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

' B! \. r& G2 }8 S6 N J

} else {

; m) b, ~8 x3 F7 x& f

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

0 x9 H6 z3 R6 f. R- o! v0 T

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

( u- [2 x. |4 P. L3 d$ {9 P

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

+ ^% s3 {" \; w6 u3 T! s, o1 e5 E

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

! _4 A& `& j0 H

DDF_BACKGROUNDPAL);

) v7 M5 J9 O6 j1 ]/ d+ D

}

. I+ U7 E8 D- _) S; Z" w# o3 R* C

}

" M' W7 C! r1 y' h6 E& v8 q+ w, m

return;

& o7 ^0 c) A& r+ T1 W8 i

}

! ^+ D# w: e) ~/ r7 b5 b" g

$ f, m' A# n$ ?3 v. z$ E

+ t$ B! e9 E% j I7 O

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

' _2 ^" N; ^; H4 n3 t

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

( ]' a( y# W- r5 ~

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

% L2 i7 k' ~2 _- h5 _

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

+ |! N# O+ b! H+ E

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

2 H4 P5 d1 n8 H- e

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

& [4 ~& G$ ~5 e2 y/ V# e! ]% m$ k

- E | o$ }" s% z9 d

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

( Y' d& e$ b: ?" Y- I

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

! T e. H& |6 n

4 h% g4 C: L- e( Y! A

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

[& l, n) j4 s9 F# j a

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

0 P+ e7 M; e3 U" J q: K: q

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

4 F9 q1 q8 z3 K8 }7 K4 g: J( ?

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

( l* A7 H- ], _/ X8 N

。代码如下:

2 d. ^: M4 n# X

5 P- E/ I1 N Q3 E+ _: t

void CMainFrame::OnViewBitmap()

+ A i: }& h: W

{

F+ B$ a; p0 D* O

// TOD Add your command handler code here

( w# n' X4 r4 K1 A

CViewBitmap *pViewBitmap= NULL;

4 s9 k6 S" u2 O g

4 C* A! ]! d, n; h) x, b0 K

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

6 w/ P, ?. g% z# ?! ?

pViewBitmap- >ShowWindow( TRUE);

4 \$ Y9 M# B" [9 V9 v

}

3 N9 X. R/ H1 N

4 s( q* {' s3 [& ~& \ A& s& S

0 x. q1 L1 s* d, V0 ^8 a/ p

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

( B4 b, D C9 |) p$ y) c1 e$ A2 B) a4 x

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

( x3 x. w. ^0 B( _. r2 x7 f( c) t, H

+ N1 r2 l M+ T6 k2 k, @

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

# V) y a0 x# m* k, j! G+ h

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

# y7 A! ~3 |2 B) d! ]

( E" ?; Z2 Z+ D* M: |8 W5 z

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

9 A b% z" L+ i/ z- m) v- f

& a7 c1 w+ g3 F$ v

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

$ y, M. O8 g/ w+ `! t5 v

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

A v! @: Q m& F. Q8 D

$ [" c8 H: U1 s2 h* J; N- J0 @. K6 V

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

+ V$ Q" V& l" j; e" H+ m

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

% F3 K* e7 u. d+ j

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

) u1 y/ k# b! ]' { N$ C

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

* T1 ?7 N) Z5 |( `' d. v

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

% u) @$ J A }9 [

; z' v: w0 @# [$ s/ g

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

. j7 L; G; d8 ~8 \6 h3 k/ R; `

就可以显示该位图。

$ N" p/ q1 E* m: u$ o5 ~: `" e

- d5 \/ n, D: _$ O( y0 w/ Y0 x9 Y

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

6 F3 I* X! ]. E5 P6 O, |3 J3 c / U: }3 h: r2 s/ o6 V; _

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

/ _. r/ y; ?: z9 |1 |# O0 A( g( S A

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

) ?* Y+ k: T) G; g

真小,显示速度快。

! h- C" x5 N) R8 O. _ [# O9 R

8 U3 }: E+ `5 M- _5 F

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

- P% U# \' u, _ m) M

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

) N( _& T+ T7 h6 Z9 e' R

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

R/ P) W+ H: y# {* O# T

/ e* {' _. p. v8 O( n; m

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

! T4 K" V: n- _: i* \* @

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

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-6-12 17:09 , Processed in 0.435467 second(s), 51 queries .

回顶部