QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

* H/ ~: ?. }: ?. @

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

0 E$ `# l0 H% c# |/ ~' \3 T

张义云

1 |7 n* U: e- l5 G! b' }

9 y. x9 B% d, p4 b9 ?1 k

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

_& u7 Z; d5 m/ Q6 V, e" l( ]

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

5 q! W0 a0 b( u) ^, r* E

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

$ l/ Q' I2 S' A. \$ C. M

1 g8 \0 Q; \: Q$ }8 z

---- 一、BMP文件结构

' l, w$ P) g7 i8 L6 y5 ~

0 _5 _4 T- ]/ ]$ c3 p

---- 1. BMP文件组成

+ ^5 @( m+ n7 T/ e0 B* ?; f

) W- C: I/ E7 g$ W+ D

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

: x4 B% V D: m/ l

5 V' S* |* o+ Y7 G( w+ @

---- 2. BMP文件头

+ ? x; ~( N! k, g* a. Z* s6 ?- K

, s9 u5 d9 H& E5 K- s2 V

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

. X/ i9 t( V! p1 G( T; \0 U

% ]' P8 v+ |, T& T0 ~& U' Q+ x7 M

+ d/ D: R- ^ g) g( b6 S

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

/ ~8 t6 G6 Q5 G+ D; T

2 y0 E* ^8 C e5 t

typedef struct tagBITMAPFILEHEADER

w7 F2 J% X/ {7 _

{

4 k6 b2 e9 f" B

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

" Q3 z; [! ]. K& [/ ]1 r

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

1 L$ Q8 J2 G" G7 ~

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

- J" c: U8 P( g- D

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

& ] }0 G' ]# T3 h* L3 ~5 ]

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

9 u( f' a2 \+ L

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

$ `! S# l+ L( K

} BITMAPFILEHEADER;

& G9 {) T, i u' `+ r" y4 I

( c$ _% b# `& R. b+ J8 W A

5 U! G; x; ?' V% m' I$ J

---- 3. 位图信息头

' o; W+ _" J7 k: d; E( A

----

" l& {: j& _1 g* i

! Q7 x( a: q7 X C4 k

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

a; Q w q& _6 N7 f

typedef struct tagBITMAPINFOHEADER{

. t5 k" t1 h, v. d' R

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

) ~9 [0 O9 p+ R1 s# l. c

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

8 y* D. E" v% n& B0 b

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

* R- k+ \+ V& ]# Q- C. I

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

9 w; P0 r, t( B9 v7 {9 ~

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

7 Y, ~: b0 Z$ t% Q1 g8 O7 Z. G

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

: _9 M1 |$ r# }" K) z+ K8 D: q9 @7 L

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

& G1 \3 V. P/ B1 g! s

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

" {& G" j9 @$ q: a4 b

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

2 b# e5 @, u1 u. Z/ n" P! e

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

0 t4 a/ ?: `% i4 T5 P5 _

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

9 c5 n3 P0 o$ K$ b+ L& ~

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

0 P5 d1 v( h; ^$ m9 R% D- W& I

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

5 _/ i1 i4 o7 N& q

} BITMAPINFOHEADER;

/ E8 {0 o; @. O8 G U/ n

4 D) j4 k0 T5 \+ {0 y1 M8 B

5 E0 ?' Q8 X0 r! C# [

---- 4. 颜色表

* b! m; Q/ l8 Q3 ~+ Q8 z8 l4 Q

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

: e" Z" t: g7 F, Z4 r5 [

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

' |! J# ?% }9 N! a

0 R5 w. e- y! k( F/ T

typedef struct tagRGBQUAD {

1 l2 |6 F+ E' T& y1 w

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

8 w$ o. a: s! M

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

% K' z) k5 p" e% Y2 O

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

$ b5 j `" ]2 A0 U3 w6 `

BYTErgbReserved;// 保留,必须为0

) c: W/ }$ b- l( d

} RGBQUAD;

9 l* g& e8 L6 j' \- W

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

" d* N; A. O" P7 f7 @

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

5 E: L" `! B0 m X

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

9 Y+ N" ?# g1 w4 C$ B3 g

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

( ?4 Y# R( z( o$ K6 `

typedef struct tagBITMAPINFO {

% Q+ U) G* x7 J, S0 f3 ~1 l2 n

BITMAPINFOHEADER bmiHeader; // 位图信息头

+ d1 b z1 v4 `+ \; O2 o2 Z

RGBQUAD bmiColors[1]; // 颜色表

$ Y. ^7 C1 `/ g

} BITMAPINFO;

! w, w6 Y# O' b

" B- {1 Z/ [" Z. f8 M

4 h) |; `7 O4 L

1 p9 w/ f6 h. k7 t5 I. l: j

---- 5. 位图数据

$ S& H- l% O* N5 e5 O

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

' u( i m- G9 x4 e

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

/ V0 F/ ]: ^. d$ l

; g8 k' Q+ [6 r* P$ w9 |! u8 Z j

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

6 G0 M4 H. y- C; {5 U2 `6 n+ e

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

# b, ?* F! I; V7 @4 W) K

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

& x0 N X2 r. O

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

/ T! `2 B) m# ^

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

3 B* }) V, Y0 L; n. a- L

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

4 R2 F' M& m5 A# B& u$ b

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

) [2 I# }( e$ _5 X5 }0 F

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

. h+ q0 h8 D4 }

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

$ S9 N/ j1 M+ r' L

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

0 P; E$ {* n& u3 d& E

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

0 g- r) Q" a$ L9 Y, R7 u* v5 u8 w

DataSize= DataSizePerLine* biHeight;

6 R$ f+ `( G2 Q! ^

4 j2 d6 D4 `) G/ ]! n7 @

/ H3 s, v9 Q1 S4 G( }

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

0 M- V& O% s, I: r

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

, ?6 l% o7 ]; n# }

+ E2 o% I" j& |7 e U

---- GlobalAlloc(GHND,FileLength);

3 ?$ [: [% Y: m2 a+ h i

3 }+ i% l$ r; J) q

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

9 p; l1 g, Y' }, ]! ~8 N

2 D- ?. E: {2 R' x. A; u4 X1 T

---- LoadFileToMemory( mpBitsSrc,mFileName);

8 e3 P8 P% R" e" K! ^

! l% Z1 e9 f2 X) Q' K

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

9 \3 d# g( B k; ?( y2 h

' u' Z$ o8 L1 X! L, y( @2 O

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

+ A) |2 ?( E l+ J# [

DC,

, ~7 p! y' f# O7 f" h& d/ r

) o/ ~; e! c9 _6 K) K r# p

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

! k4 ~/ [( j1 S! o

6 D5 T1 l/ B. Y

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

7 M' O0 R( V' q& ?) w$ Y/ U; N

8 e7 H: b5 E7 M- x: f. v4 X1 s5 r

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

/ w( O% |; D5 O4 G" A

& }9 l% s" j7 P

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

" A4 F! ~7 s9 R

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

" o2 f4 }3 }: U% z$ H. J9 o

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

* y& i0 v1 b4 K, q1 J% w

4 @' G$ W, T" j6 _, v* b) S

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

. u7 F3 U# @2 [4 P) Y

! v6 B- A" A* |6 W8 v

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

1 L' q! v; }3 F! m

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

! p7 x4 k; L5 H3 f

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

( e- ~ {, a8 o, I" W- W3 O- O& a x

5 d: [# `" u6 W5 f, y S- e, M

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

& o$ B- Z) ~' Y, n4 x$ H3 p, M

; y+ k J5 Q. z4 N

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

; `8 _. w& h& k$ H+ A8 B) m

2 `, [! q' u& L3 \9 Q1 ]9 s

---- GlobalAlloc(GHND,FileLength);

+ S3 ~8 P) e- `

1 d; u) z: V5 @7 i1 p

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

) k! F* e1 P7 C" ?4 e5 u

( ~+ [3 @+ Y2 B5 w9 C- o

---- LoadFileToMemory( mpBitsSrc,mFileName);

9 l! x. `3 o( m# `& n

( J, X8 S( `( j8 P: Y

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

. _1 J( d+ m* K8 C% {1 |

9 D- l. \5 ?9 ^: y% Q' R1 c& C

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

# [9 ^3 I: w4 x' m9 q' c+ ` i

0 G1 h1 L6 d) ~ \9 Y* r* G

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

4 o1 c$ H: A: ?& Q8 N" x* m$ S

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

! ~! _# {* V& z7 F8 }9 q/ B

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

- _6 T4 o/ T$ K/ t; Y4 l

$ @1 k) ~. }7 O# P

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

- B; F+ S0 |2 S! W

% w2 x0 q6 a. r& |

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

/ g* m9 g Y2 I& n6 p

# _) C* [" e* M# c: P

HDRAWDIB m_hDrawDib; // 视频函数

! t5 { K$ ?5 X7 Y- s3 V

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

2 S& F B' ~" Y0 M: r7 u

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

; S: m0 i" s+ i l/ ?0 {

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

4 Z% x1 I8 x4 S# A7 T8 T# ]) n, {

; t: d _- I, u7 ]: l4 t

8 {6 B1 `& @% |/ }6 q) P$ C: D7 e

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

7 ~, b/ L% _! a, u5 D. O& [

---- m_hDrawDib= DrawDibOpen();

3 v6 ]* C, [$ {

" T/ n! R& R& y! E" _" I

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

$ g2 v- ~" e9 R; l! F

: O/ A/ j' t' f3 D+ J0 b- V( [% \

if( m_hDrawDib != NULL)

4 S$ I/ x& X, `4 O" T- Q- k

{

8 k/ r6 @/ W3 R& C* l/ S5 a( {) Z6 D

DrawDibClose( m_hDrawDib);

4 W8 V6 l( N6 P. e/ n8 c

m_hDrawDib = NULL;

; j9 m* S5 ]7 c# D/ P

}

8 y1 l% p2 N( B9 E$ t% M1 G

8 n5 K! P) D' j$ O6 v" W

& r6 N' N( @, J: k) W E4 s

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

, u9 T/ G1 Q2 V E' l. E* l( d

voidCViewBitmap::OnPaint()

" H! h" M6 B+ W3 y

{

- o/ N5 @( D' v9 z

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

7 @/ A+ U% o) J% B& u7 v7 E! w

GraphicDraw( );

/ `, d2 h* K$ W

}

~ Q) P0 e; s X, a1 d' L

: u3 W8 x: S" P) C

voidCViewBitmap::GraphicDraw( void )

& E9 C. A4 |# g% Q/ k7 f2 `

{

" V8 O, l! ?: o$ j$ f E# D! K9 ^

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

5 X/ C' d( x3 Q) B! `& T' `

BITMAPFILEHEADER *pBitmapFileHeader;

( d# n" f0 J5 Q: ?. b4 E4 ]; W G4 ]

ULONG bfoffBits= 0;

s- U+ D' T t1 U

CPoint Wid;

6 o0 x8 X* O2 b' r$ i# H$ n

0 P; a! j" u$ p: I) v0 T9 g

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

9 F9 u# k7 v2 \3 d

if( mBitmapFileType < ID_BITMAP_BMP ) return;

; O" j- B4 s/ g, ^! _

$ ]6 R6 R" L7 }$ W0 D

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

" k5 t/ s3 n/ a2 f5 R! x) U5 d

// 准备显示真彩位图

1 [6 u. l! Z5 ^7 o* B; I7 I

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

$ g' s3 S }, |: @3 ?4 J4 H/ b8 k8 E

bfoffBits= pBitmapFileHeader->bfOffBits;

8 N) t y3 f, s7 v6 ]! d

4 ~5 V! G' |' {1 Z

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

$ H' R: R% \5 e

# \% \3 _# Q3 v' y7 |: q0 `

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

" L- ?- c) r7 a* I2 q; l' D

{

+ u1 S+ ~3 Y% E- G) K

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

0 R" ~3 p" |. b$ W

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

0 F6 w; r7 g3 g2 f! F5 A

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

! O% t% t/ D/ T( N3 y

// 建立位图

6 A* `! D+ y+ R" E, ?; W

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

9 D e1 Q M" D1 Q* w

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

3 v- }1 ?3 p5 X" h* C% G: I

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

/ [ C: ~6 W" y/ u! w

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

9 l, ^, K/ K, z

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

/ a: w: V4 U/ h5 G! O

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

5 @- b$ N' R) Q6 U1 k

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

* r5 |/ x$ S9 m; s* t V

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

& a' S) h+ m( k% }9 U, L

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

) S4 M- i! h( K1 I! t) Z6 S# o

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

; w' W: E5 c* C. o5 p. j& P2 ] Z

+ L$ w8 n2 u' G) ~7 z+ ~1 I

if( mFullViewTog == 0)

" ]0 r4 D0 R* Y) z

{

2 I+ Y( G; w m9 F: S

// 显示真彩位图

+ ?0 A3 [; B5 ~& w: P9 ?8 K. W' j

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

' u+ n5 V7 b) F# l% ?0 `! z9 |3 v

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

6 s, g- V5 q, R. B: s

} else {

: S7 M x6 W, Q- G6 j: O

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

4 T; k( z! N% M, V! v# U$ A

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

1 y! T# L; i% W$ R/ ~* w

>biHeight, SRCCOPY);

" r% ?) ]) `' \$ @: W

}

, @+ a& F6 f+ b9 E5 s

// 结束显示真彩位图

% w) w) S* j* T j! A5 g* B$ H2 I

:eleteObject(SelectObject(hMemDC,hBitmapOld));

; X7 Z2 p# { Q( W

// 删 除 位 图

. H9 h% t) P( v

} else {

5 E+ h- T7 i3 c) r7 d9 D' o, B% i9 Q) B

0 c7 ~ U' ~' e" r0 [( k

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

6 o4 N& s# Z$ F5 o

) I) T, F; u0 z+ Q6 |

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

$ ~* r4 Z5 r9 b5 v" Z, r3 C3 @

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

1 y T- B' M/ V+ d1 {# }

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

2 _; N( @4 o, w

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

% ~: B- Z& j; M$ r3 ^

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

. G" ?, v/ ]% G: k, h9 b

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

# T0 Q6 D$ r# W

1 P6 J1 ~7 a j

// 显示真彩位图

, k7 _; p0 a9 G" E2 W

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

+ S( y8 ?+ K9 {/ m3 m

' d% I, g8 ^1 m; O# u6 I/ Y

if( mFullViewTog == 0)

' \) x5 t6 O& C' F x- f) a

{

& i' m' p6 b7 D% Q

Wid.x= mDispR.Width();

7 q9 d9 B9 ?+ j! T, _0 @( O

Wid.y= mDispR.Height();

$ M4 E5 d! i" h3 X

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

- `6 M1 v% ?: S' K

if( Wid.x > mpBitmapInfo- >biWidth )

4 C1 E( e; Z" x8 C7 }9 ]* C

Wid.x = mpBitmapInfo- >biWidth;

) |3 Q. o% R# |- y7 Z. s4 Z' }

if( Wid.y > mpBitmapInfo- >biHeight)

& V& S5 n1 [- w+ [, p) p: ?

Wid.y = mpBitmapInfo- >biHeight;

" K; F j9 j3 ]4 N( `: j

# Q# b3 K. g% _: q! U: ~. r! U

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

. Y# ^% n* d+ i7 X8 Q; e

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

+ C, d5 G" I' g) t* E/ c

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

6 v" r4 B5 Y) k" X6 X7 \9 Q

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

: ^# \2 K5 H$ T& O" y3 Z5 Y1 l7 I

} else {

& F ^1 _- I: Q! X, O8 \

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

4 @. X' W8 Q' M: `# v

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

: t3 ^$ \6 `- L

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

1 H% @; a; T+ b

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

8 m1 |* \' G4 ], z; I# [

DDF_BACKGROUNDPAL);

. m; [( U; H+ {

}

: z" |# J, P M: b5 [5 }

}

F! S: J% s3 [" n) v6 S

return;

" d! U/ A1 Q8 U, j& m9 X

}

" p* U5 w) ?2 N+ w

3 S. _$ k# E% a, X0 n& s

' D0 P3 r4 i" [; S

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

, c8 a! \/ @' S7 X3 t, E/ O8 z

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

/ e2 ~6 E1 s& O* p, i4 S# |8 g

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

* h7 w+ l) f+ l$ n4 a1 m% A

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

! L& {- D' r3 \3 y4 V2 J

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

' D/ X3 p' @. H4 k$ u2 M+ C. J K

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

, a) A4 M2 M5 P" x$ ]3 G# _: ?

' f! x' @" ^, L/ W# d

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

8 J3 q1 o/ F3 `

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

% y6 i8 A6 ?4 L4 _. d9 l! j

" P& C' O) L% J0 T9 m I! b4 B% b3 Q

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

4 L& r2 }3 b7 }

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

9 T; r. g! V1 E9 s; ]( Y$ K* S% v

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

, D) k& }: H C T9 ]- U0 ?

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

( Z2 w) e8 A9 }. J

。代码如下:

5 ~8 ~" ^5 X; V+ f* ]& @. E! z

! z W1 m! ~: [, b

void CMainFrame::OnViewBitmap()

2 i* a/ E8 N' K3 M: J2 x3 `( o

{

' V4 G: Y. _" M( k! p D

// TOD Add your command handler code here

0 K8 l" C4 w/ E

CViewBitmap *pViewBitmap= NULL;

: ~8 J( y! g, y/ w+ y5 x- n

$ {5 K4 P7 H& h V8 F& K! C6 N

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

# ?9 o. S2 K- g" Z: M2 ^

pViewBitmap- >ShowWindow( TRUE);

0 f/ t" q; o' b5 i

}

1 c$ |8 o8 R, Q/ J

% ^. G1 M8 @! Q1 s/ T: ]

& I6 q! W% L- c

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

% W& k" }0 b9 M( g

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

2 M& Z2 {% q$ s: p, q2 t

* a2 Q% r& N$ B1 z. u8 Q

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

& t6 M% O8 p7 z& l9 |& e0 q

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

+ H* o' ]0 e& ^! D/ h% |$ i

( I9 B6 i& c, y( w! P J4 a

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

+ H/ W4 f; F6 {; P+ Q

' j c" |0 v+ E. u/ U1 H K

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

5 @8 `" p8 E% d6 Y' S8 a$ @1 E

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

7 N+ a0 ]. I. I# |3 @! M2 v

& l& h6 J& ]5 F" T

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

0 J( G3 K, b$ S& o1 q: f

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

7 l7 p7 p* W4 _8 k6 p

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

- ^$ c% g7 B4 n# v# K8 u8 p

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

0 q' a8 ]2 N0 ^

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

& R* R2 ~4 D! P0 T

) d8 f N# X% j/ f' s% y

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

5 p* v+ b# _0 i, Z. H

就可以显示该位图。

8 Y' ]1 u: f/ I

3 Z5 @/ Q# r( l8 P K9 w$ y* n

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

- p* i2 W p2 `' { * G$ }4 G4 [7 ^- D& Y% z

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

% Q6 r H7 j3 |# T! d" ], u. \; L5 y

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

+ O5 p/ f# [9 S9 s* O. [; d# h3 t: A

真小,显示速度快。

) w1 x5 [1 d. ~4 o, @1 w9 J

7 d# Z! Y+ z! ]4 X# f; j; t

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

2 D* t' s6 {9 ~ O0 U8 S. Y/ a

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

8 X' u f$ I2 h% M& _

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

z1 D* Z3 Q. v0 U" U: z, h: k

7 a$ ^2 }$ z0 z) r/ Y% w) H; I+ m

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

: R/ g0 l8 v! {$ R

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

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-21 12:25 , Processed in 0.455618 second(s), 52 queries .

回顶部