QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

# A1 |( A% V5 g, p8 L# M& Q

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

0 o4 Y/ U, I& o6 |

张义云

2 b5 q a8 V) r/ X

' |" s7 t' e1 }+ G

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

: n3 y4 v, a, T8 }

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

! U) }/ [* a |) z/ E% Q; b

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

! ]; l( J0 m! o* j4 D' F

* w* U8 @3 i7 y8 J

---- 一、BMP文件结构

( t. W# h& H0 @$ x

5 o q, j+ c1 Y- ^

---- 1. BMP文件组成

8 @2 T/ G9 V; T9 d) m& @

* G3 r' |* P$ b9 U

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

! u$ t. M+ W! a t1 J1 f( S

# B) r) x# o+ R. r' n

---- 2. BMP文件头

6 b/ v- C S& F# K. A, t+ d

( y8 }" d$ T4 S% b8 R9 ~7 Z8 L G

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

( e1 U5 }# Y: |. c: V5 ~3 o" k

) j. {2 U, Q1 }; a/ M6 {

7 X+ s |* j( |3 L6 T

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

$ [2 v- Y( f* [( K5 W

4 E0 o- `3 T$ _! `6 O- h- x' G

typedef struct tagBITMAPFILEHEADER

6 h. B+ A( U* n j' b! H# `* d

{

- e# x2 u8 l+ m2 |8 m

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

9 n/ W9 Q& X* Z

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

& T o2 }" d8 P7 X& F+ B* `

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

; S$ J% B) _/ m

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

~1 I) v4 p6 y i# _/ k" x

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

* F/ n1 R/ b! j% m" C6 t4 j

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

) H1 ]: E: U, A$ K

} BITMAPFILEHEADER;

& u' i' n+ K- x0 Z- ]9 g

: q8 Q6 C- |& o

" }2 P I# A9 A" \; `( O

---- 3. 位图信息头

( x0 w0 h+ }6 w; O5 \8 b' S3 f

----

# ^3 a( a$ g5 E

& V2 b# |4 D. ^3 d

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

! P G1 f* G5 F' {

typedef struct tagBITMAPINFOHEADER{

/ ^3 U. n- {# N+ q: d8 S6 ^

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

, ] V% v% |# l" q

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

* \' e* ?4 x7 x8 @! I3 ]7 x* Q

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

/ I. _4 Z- [! p" c

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

" F! a8 N6 x. I# N$ E

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

" k, [, e3 |! Z8 h# k5 n& ?

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

! s& a$ D) K3 o& R7 p

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

( B+ }5 j" n% K) U

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

# {9 b8 N: @! }0 O, j+ d! S

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

- t4 B% L% G* g; \/ c- k6 U: b7 P

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

0 P% R5 z* _5 c% i T* i

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

* W. F4 m' o* m4 c7 V4 r. N+ y& O! W

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

; a0 W. k8 ^0 J; ?( [6 o5 c1 S

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

8 |$ Z3 Y- K0 J

} BITMAPINFOHEADER;

/ A: \: c0 A! q+ y* w

. ^ k- J5 o- P8 z( v7 b

v# u5 y* t- n6 t+ u" R4 ~

---- 4. 颜色表

: Y3 N% F" M* x7 ]

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

1 Q7 `( q3 T/ |

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

9 N( l( j8 e! t- W; y

; _. h' I$ j( n3 v, ]

typedef struct tagRGBQUAD {

7 S$ R6 N; b2 a$ e# g+ Y

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

9 T. v K) w j+ Q3 E

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

, v3 t ~( l4 e$ p6 k9 X

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

- ^* [5 y& i% |" H* J

BYTErgbReserved;// 保留,必须为0

: Y# [2 T% Y+ f9 K( t

} RGBQUAD;

% W" K0 l2 \3 V7 Q" z7 v% I' j

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

$ I( v) Z4 J& R" y y, \

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

) a8 ]+ J- Y# k) u0 r

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

; f2 d1 Z+ I! m/ Z0 f! q7 U

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

; h2 _" A2 Z/ \: B; k6 d

typedef struct tagBITMAPINFO {

) d1 O( a ^- I% `

BITMAPINFOHEADER bmiHeader; // 位图信息头

! p8 [6 k) y9 { b+ D! j* h' W" [" U4 `

RGBQUAD bmiColors[1]; // 颜色表

5 a5 ^* i+ ^" ?3 q+ ^) G

} BITMAPINFO;

# N. X9 j6 P, ~( }1 {: G, ~. h% p

. \/ k; M; j9 U+ E* R6 K

+ Y: `3 [% W- C4 K' d1 R& r

4 Q8 K# q9 R% o( @+ g2 U

---- 5. 位图数据

% V# @9 ] j, | @6 l/ K

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

z' Y2 l5 H4 Y

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

; A6 O8 @/ v; I& h6 B% K

# {( D0 ?% Y2 `; j1 H% [

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

1 s, o' p# z; w! j( s7 S

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

; f4 w+ |0 X0 r* o

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

$ Y, ~0 p/ G5 f- C5 D3 x

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

5 W* M% k1 I$ h9 I

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

2 j' C, R7 c- f. `8 m

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

, J* U5 k0 g1 I8 G& v

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

5 u7 k' @" g* M+ [; `4 D

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

) I% |2 I: @9 n

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

8 b/ E9 P5 K- N# N- }) n

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

- t" Z( p; r- b% u+ H& w

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

& m5 g' F/ f3 v# t' M8 G( G6 c2 I

DataSize= DataSizePerLine* biHeight;

2 s% H8 e! W3 \- C* `+ q2 M

4 C. p- c$ A7 W# s4 q

% Y1 m: z: Q( \) n$ g: Z2 y

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

" H+ }) A/ A5 x

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

1 D! l, M- S, I7 _- p& L! y

! E) L5 R. `! a8 |; P. {

---- GlobalAlloc(GHND,FileLength);

! {# ~# X( q9 ~6 s3 s

6 A/ b9 k. a. l4 v$ p: {+ i

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

$ a" j9 s5 H5 W# `1 W, h8 O

" M2 J% J* Z& f* f/ z& c* h$ V

---- LoadFileToMemory( mpBitsSrc,mFileName);

1 z0 b* U) p9 Y e) Z8 |

8 ]: L- H0 h' ~ W. h; }! B: F' J

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

2 t+ ^6 n) o1 K& R4 l

% k8 g' v0 T6 D- y ^

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

) i* p' S+ u% Q5 c; [; l v

DC,

! U0 Y% ]" |) |- c5 u4 b

5 n0 S& K0 R' N3 T0 h6 x* z% `

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

& Y" y1 ]" p6 I% @- M8 Q( X$ |

6 `; m7 Q+ g0 T, K$ s( |. J" O( v. c

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

6 \7 r8 }' U6 R8 `0 {) l8 P

7 G0 q, P4 q0 t: V$ K3 ^

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

2 l3 l/ u; c0 w5 Q9 }2 z

) l3 R; D% a" @& S

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

! _4 Y9 W' S- W

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

, ^- H3 Z, b& h; k2 z5 t3 L

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

4 j4 c9 f9 t) ?* v

/ `8 w' Z( d5 k/ C/ I: Q

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

9 u5 ?$ A2 b, u4 o

8 l- H; n2 e8 M; \& |/ O2 J

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

5 {3 i& @/ A I9 c! {

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

8 T* c1 d: [$ Q" X$ B0 {3 Y

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

7 S7 q9 @- L. y' ^( @

6 I: U4 r$ h% t# t, P4 ]0 n. w

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

- q! v- I1 x6 L7 }; ]

6 `' ?+ G$ G ~. `

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

/ d* j' C, H6 C# B: l

2 d, \8 j0 { u% K

---- GlobalAlloc(GHND,FileLength);

& z6 K0 O% H( F

7 T, w6 h$ n# O4 l( F: [

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

8 N2 G: k5 B3 `) M

3 B1 u7 H" A0 O. b

---- LoadFileToMemory( mpBitsSrc,mFileName);

1 a. w& B6 q7 n7 }7 S: o |

" a' w& g0 M- y

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

6 u' E+ s$ e6 f8 a) c, M* V$ p

/ o% v% O) m; n0 u# Z/ J% l

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

& T3 f8 y3 C6 X4 q

* L% c: g- e- e

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

2 b+ M& x- f0 m, p- @

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

3 |* M X2 }+ k9 j6 |/ J# L! b

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

: j) N' C9 f% ~. z

# \1 v9 Q5 A" d4 z+ Y% Y

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

3 i, P$ U9 M9 w7 k5 X% u1 I6 b

! P h# D! \* R- `! x

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

+ j5 Z2 M8 W- C8 k; V4 K

: F3 F2 ^ I7 s v- P

HDRAWDIB m_hDrawDib; // 视频函数

- H0 H! {$ p9 p/ {; P

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

4 g% r% ]3 \; s) A% i! Y

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

v* y* w' ~1 a, \

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

8 a# `' B2 e$ `4 e& U, c! e g" H

6 C) Q! q; @4 w

6 N* s! l+ g4 n. T% A

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

( e# M F8 ?' w' f/ I3 c1 v

---- m_hDrawDib= DrawDibOpen();

) l% `8 D! v% H) O0 p

# Z; l$ i+ J0 _1 _+ t* P

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

$ N8 P7 Q5 O% ^/ b% s. a

& A5 W$ ^1 {/ T F0 D

if( m_hDrawDib != NULL)

5 e1 A. e% }: R' w( C

{

* t3 ?- G* d# d' D, U

DrawDibClose( m_hDrawDib);

) Z; K3 A: y! b0 J5 D. t# t! d

m_hDrawDib = NULL;

4 L: _, p' ?% R& E7 I# n

}

5 n: B: F7 i/ X& x

5 M: I6 \" t4 R

$ L; @8 g; G$ d" a" ^: w+ w. `" z

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

' V) Y1 j6 G- z) s

voidCViewBitmap::OnPaint()

8 i, l# n8 W9 Z0 q

{

& D, g) h G/ o. E

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

k4 V1 b3 _1 b' U# R5 P& ?

GraphicDraw( );

, g9 T0 z, ]7 D/ M8 t

}

- d% B# L+ |$ @* q

8 a- R( |& v V

voidCViewBitmap::GraphicDraw( void )

# f% |& r; P; n9 ~

{

$ [8 n- ?2 W6 K' b# @

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

, ^( J5 U3 w" z

BITMAPFILEHEADER *pBitmapFileHeader;

' z- R6 ^& [2 \; x" S' a- @

ULONG bfoffBits= 0;

+ ?6 V+ ~, P* r* Y( K& h

CPoint Wid;

/ f" Z: |$ b9 X$ y6 s

. |- T7 ?6 b' E3 [

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

3 T$ o! U6 e" X

if( mBitmapFileType < ID_BITMAP_BMP ) return;

" @% I4 a3 B) ~& Q( Z4 j, J+ F7 P

* _6 L4 S' K1 g9 X3 u6 \

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

2 X1 ^) M* e. j' m3 V$ `, r

// 准备显示真彩位图

! E: J1 r# b( n+ z D

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

) v, v. ^! @2 m/ v6 ~1 x4 \ W, A2 ^

bfoffBits= pBitmapFileHeader->bfOffBits;

9 O6 ?$ N t, h6 Z9 S

, P/ I/ q2 t- ~; O8 w, c

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

8 M* c- ^* ]0 z. i7 x- ~- }

4 k* f: o) t$ Y( `

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

0 W# z" G" Q$ o: v& M3 S

{

' W% U7 v; ~/ o& T

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

/ x8 h9 w# |0 h- F ~- @' a

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

# \8 a0 Q) i& v' e/ `' d

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

; t: a# \% A/ a* O7 V3 Z. G* X

// 建立位图

! P0 f; [' J0 U y

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

5 Y) {+ I( h1 i) F* |: ~

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

7 p+ S* x* b' f1 E$ Z$ s9 h/ O7 S7 k

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

6 R8 Y+ t% G) O7 K! m

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

* X5 m4 A, o$ c# `

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

$ n2 h1 @- g3 d2 {

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

9 z8 S5 P& e4 e3 ]

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

; m- Y Z! p2 I+ d

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

! F6 k( W& w* D) u$ X+ H- r# b

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

. v: ]/ |; i {. w, W, { J

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

Z$ g/ ?+ M7 G) O4 o

% U3 Q" v+ \0 n( a

if( mFullViewTog == 0)

* X: K8 \$ u& b, U7 T9 c2 [0 W4 d

{

+ g @/ g- R R6 p5 q% H

// 显示真彩位图

& v; m4 H6 Q. I2 v, O/ p7 O/ I

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

% n5 f0 l) C- Y2 O$ r2 b

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

- i# A* d% i+ q

} else {

& f! h7 j' s7 J" X0 e1 R- g

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

/ C* P5 D6 `# U( V

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

* j; E# c0 | [! Q4 O( n8 V7 _

>biHeight, SRCCOPY);

6 r( c8 J$ P8 p

}

: J$ @; u" j3 R% e* t) V8 s+ n

// 结束显示真彩位图

% [( V$ N) r- e

:eleteObject(SelectObject(hMemDC,hBitmapOld));

, ~# z/ p3 N" x: g( i5 |

// 删 除 位 图

$ |# L- C, f) K" n. {$ V

} else {

. u( M2 M$ x5 M# X

! C9 f- S/ t# z8 Z5 ~9 o* W

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

4 z: ^3 Y# j: E0 P; _ K

8 d6 P) E4 r* M2 }2 {

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

+ B* o, Z2 h& \+ M9 a

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

3 k1 H/ z8 {8 m

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

% i" c8 z F1 P4 S* t* P$ M

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

4 _. @2 R# @0 k( p4 P: `

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

( N P& a2 z( r+ S: w% |5 m% y

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

6 T8 u' K7 x; Z o O# T8 t# t3 k

0 R; e6 Z6 L$ s6 E- n

// 显示真彩位图

5 |9 K, s$ O4 r

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

, l& Q9 U4 l, |$ o# e* f

7 B/ N5 x% ^+ | H: |

if( mFullViewTog == 0)

+ Z2 Q! ?+ V4 E0 }# m9 h! s; t$ r

{

6 @# c6 H2 Q6 _! O$ a6 D$ U

Wid.x= mDispR.Width();

9 J* J0 N; F2 b, w

Wid.y= mDispR.Height();

) u# j* F$ p8 E; Q3 p9 U8 e- @( W

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

W4 C9 v+ c1 d! v# ?0 ^+ ^

if( Wid.x > mpBitmapInfo- >biWidth )

4 l% |( R! Z: u2 X( ]

Wid.x = mpBitmapInfo- >biWidth;

7 s/ `( o7 t+ C

if( Wid.y > mpBitmapInfo- >biHeight)

5 k" n+ E9 J3 ^, E' k

Wid.y = mpBitmapInfo- >biHeight;

6 P" }) ?" m( U+ V8 q3 Z0 a4 C6 Y" a0 R

& h) B0 W4 ?0 ^3 Q! g

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

. W7 @% [9 `& y

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

1 Z y7 m0 f: r S5 t; i

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

' s. a4 q8 i, B& k$ W- Z

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

3 Y$ _7 Z' \% f) ]9 k# P/ B' \9 X

} else {

$ G6 y( O$ R1 N$ f% M" F' m

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

2 ]+ R$ j+ {0 L4 Y

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

, C, g1 r7 Y, x! @% p

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

% R- m* ~5 s6 K6 _2 @- T4 h

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

3 X/ J/ z! k; c1 T

DDF_BACKGROUNDPAL);

4 m$ ^$ t7 w; m

}

) U9 r) m7 E" n5 O

}

3 ]- {; q" b d R! V

return;

* P! D# ]+ e; \: n& H; U) F) r2 y

}

1 n# I$ w; c# q

# J+ X; D" ~% r. k8 i8 w

4 X" D$ n0 m+ t, G

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

% }) s6 Y( G2 Q

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

( W7 J* ~& [0 e5 J, N; z

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

" ?, ~- i5 E, { S

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

4 q/ U; E$ w" i" O7 \; y

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

% b& q, v+ s4 r9 P. k3 l3 Q( F ]9 X4 u

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

9 Q! x# ]" K" ^7 H! a

4 ]. T( g z7 o% P1 D( c

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

% W& Y h2 F* B% E' i& G

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

( A' |! d( N8 R' Z

/ S7 o+ _6 P- o: V1 A/ D

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

/ I9 t# q1 F# ?

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

, n5 O6 f7 O- P) @

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

( p2 u% w3 h( m

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

2 |6 H- M# V. B

。代码如下:

; @7 i+ `& x" @. a$ g

' |* }2 ] f* a+ C' [. {( m. H4 p" K- l

void CMainFrame::OnViewBitmap()

9 C# _1 N s' [& v3 x: q

{

" M2 x* r y6 g* R( M+ I

// TOD Add your command handler code here

9 O* x# y8 T% Q& E) x# O

CViewBitmap *pViewBitmap= NULL;

; @ ]& r5 u& u6 } i

: e4 W ~+ {/ k' w

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

+ S4 I5 X* c$ z

pViewBitmap- >ShowWindow( TRUE);

1 {9 Z) |5 p1 [

}

& t* U( ~& r- z+ v* r+ h

3 E; u: e; N ~

" T/ a/ J% Q* r/ \( ^& N

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

: P! M& {7 [4 y* I& @

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

/ W- G- U2 Q' m

) F4 I, z7 h) R5 _7 i

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

# @" W, {7 a: n

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

7 S0 y$ [6 F# S) S4 m8 B4 R) [

- I a. Z( G" G) c; G

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

2 i1 K8 N4 r" B# ^

! W7 C5 a* R1 Z4 k0 H8 L/ _# o

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

0 y8 @8 g2 e' {% D

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

( y# Y0 Q4 s8 H! G% n

7 T n6 ~4 o! R: r. e0 O

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

2 o' {/ c6 P6 P6 Q: ]/ T

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

# P/ Z6 Z9 K: G3 ?2 w

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

. ~" a& |. E5 W" W7 j H% U3 F7 e

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

+ B) [% Q" F4 a; q

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

8 _" J8 K' E1 l% j" F! l

' |) N+ `0 p; ?3 }- c* q

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

- }$ i! K1 I7 `! }, y( y* a! y

就可以显示该位图。

$ Q$ g7 u$ B( j

) u- j4 A! }0 h( H% o

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

! f' w7 c3 q/ {$ A# ^ + @" _: F4 u/ s0 I" U8 [4 X9 z: ^

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

# Z* I% K8 a& O* l. m6 r

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

' ]5 k4 f! [0 u5 J6 }% T

真小,显示速度快。

\" N7 W& ?4 A% h$ A+ F

+ _+ h9 b1 W. E% L# ^! S

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

& T8 P. v) L$ v: G- y1 z

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

" `7 g a+ R$ [. x( [% o5 \1 H1 {

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

& T# `+ F2 b& E: F

! C; F5 p6 O# i% K. r* h8 V

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

' I3 s0 L; A- R, Q

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

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-8-24 22:56 , Processed in 0.471558 second(s), 51 queries .

回顶部