QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

8 s( v& L R7 T1 k$ [8 ]2 E2 Y+ E

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

* u, ~ }4 M' R- A! _

张义云

+ m; m0 F# t- K0 I7 Q. ?! ]

( L5 b( P3 {% U4 u, A

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

+ S$ d) c6 }1 @. Z. {

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

- M1 P: ~. @* L) j' ~% `

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

3 j1 i! E3 C' B" Q5 y

' v# P0 K7 j; X" @2 o) K% D

---- 一、BMP文件结构

% _1 X2 R9 V& p; z i% e+ z

! a! |# E8 R; p* R" j

---- 1. BMP文件组成

* N" h+ G! M( D: s3 ^

2 g" u' }, F* v# a/ S( w0 t

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

' f+ ? v7 Q" Z: r) b2 o7 p! @

( k) L+ e2 u1 s

---- 2. BMP文件头

( c' j7 p8 I& B! I" v0 p. I

% s1 s6 ?; ]; H5 W+ `" m+ H+ A' C

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

9 p2 C/ o0 ]) P0 o: K

。

5 ~. b" K7 s4 `: J

( g( c( t" x, G" Q

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

5 J! d! ~: S' g( M+ Q1 z8 E

. m* U5 r) J& V6 E' E$ C2 M

typedef struct tagBITMAPFILEHEADER

, l1 O0 d7 I7 c

{

# Q& T; R8 i) I! G- o$ w$ V

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

7 o3 q0 J5 S" T# V' Q w

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

8 F4 Z/ y- J6 S/ j

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

% L5 _: m# @, @8 Q+ s" d

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

0 z1 W. a, v% o& \3 d2 k2 J

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

7 Q) {1 b; t$ U9 J( H9 y. j

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

$ |, X# p/ L" R, \/ k0 ^; @' E6 _

} BITMAPFILEHEADER;

9 _' v4 w8 w; V( b6 @+ V9 p

- z) Y: E0 z! G1 ]5 x. M

. o& u& S/ X' Z2 s

---- 3. 位图信息头

* S/ Q# O+ o1 Z3 {& |6 E

----

0 t) H9 R3 r0 v7 r

R7 k4 h7 _' c1 Y, g& \

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

$ f* `' J% k$ ~% M. f' r

typedef struct tagBITMAPINFOHEADER{

& v2 _* W2 j! w

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

7 y1 r% B3 I1 F) n9 f

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

: t7 R7 [: i/ k% u

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

; t; H1 e$ G; @. @, x

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

\1 R6 V; i: F, [ P1 A. g

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

2 W; b9 \9 _' y

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

, w. f/ S& k' }8 n J% f) u

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

8 R! @6 }2 i' a

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

2 K4 m& u e4 v# m3 r, ~" s

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

8 d' M. d9 d( V5 I

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

9 V. r8 S$ k& p8 A2 d! h, C

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

H6 Q H3 W n1 i

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

n& } W& B/ @( G% O! N

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

+ {; s8 [/ @" U

} BITMAPINFOHEADER;

8 h4 t8 j& p& `) b( @

/ g5 }+ K$ c/ ~' a* e

5 g2 u J9 ^ \( N

---- 4. 颜色表

2 ]7 A' {4 ]1 D3 c% _; d9 Q

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

; A7 z- Y$ v( ^ I+ Z# v6 }8 ]- W* t

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

0 \! c; F+ ?+ j, N) b; [% G! g

% s- G9 t% s" s- O' _8 s; w

typedef struct tagRGBQUAD {

' ]5 f% t( ~! B3 a0 q5 X

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

0 M e2 X) S$ f5 n

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

6 L# m" j& a( @2 t6 t

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

; |: h, Y7 t0 _: q& _# }

BYTErgbReserved;// 保留,必须为0

3 y9 \ n5 }0 \- e5 V' w

} RGBQUAD;

$ u- U" \# O! y A9 o

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

- s# l% x3 x/ o6 L; n' p. E

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

" s" ]% j+ r. g8 E. ?0 l; B

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

+ @9 S. ]8 N3 B/ K) b

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

6 ]4 }5 m1 `& ^8 T, C e

typedef struct tagBITMAPINFO {

+ p6 r( P4 D* {7 y

BITMAPINFOHEADER bmiHeader; // 位图信息头

: {8 f/ U; x5 b7 Q2 D. g% I0 r

RGBQUAD bmiColors[1]; // 颜色表

: f) u4 n+ Z% `+ b4 T

} BITMAPINFO;

/ R6 X( h; ~- [, Q# u' ^ g6 E/ j1 M

2 `. A! z$ V$ s8 t2 r! A

+ g/ s+ ~/ M6 q9 D' t+ j5 i

; v& f5 O$ n" U6 q; {

---- 5. 位图数据

# w2 p+ h2 n8 l& [/ d; ^

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

' O7 A& h$ s% [0 ^" t% O

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

4 N/ E# w0 c% A3 N/ ?5 f! ^

, x4 \. _% B q6 W/ J

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

" M9 J, x& F0 R0 H z

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

4 K" \( k4 `0 \# Q$ E v

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

) x* `; _9 k9 g

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

. O# F% t& X6 p2 Q

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

8 X* U. w9 |. ^

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

# u4 p9 A. }6 M1 X# b

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

( ]( R5 k, P4 w7 R8 U( D

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

4 W! ]) n. d4 w) T

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

: d( g- j# q+ p

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

3 Z+ O- a' \2 g2 p& |& j5 s' Y

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

) o6 m7 I0 n0 C- u/ q7 k3 N

DataSize= DataSizePerLine* biHeight;

' o0 q- a, @3 g2 G/ B8 Z) ]

; n4 Y: E2 Y% k/ Z# A

; H3 R( L% l8 X

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

# J. S! l, k1 u/ x

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

+ r t7 D$ |- P* `$ p

' O, E# }% u8 {% E* Q d; x- n

---- GlobalAlloc(GHND,FileLength);

6 Z% Y, e6 _2 `$ e' l# p/ I8 Z5 Z

. o5 E) ^2 A; v5 Z9 T

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

+ r4 }$ i# b4 L+ }2 r

# i( m6 e5 N! v# f

---- LoadFileToMemory( mpBitsSrc,mFileName);

2 }! U0 {! x, f

- n" \2 o- p4 U% E% k: ?3 v2 j8 A6 s

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

. f% r# H5 h) Q) C: y9 A

$ Q! l. P6 w$ w

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

7 ^- r" y' k( E z" @

DC,

0 I+ t2 K$ {% j3 l6 `& |

- k8 m0 t4 q7 L' U* Y" h

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

; V7 O/ H4 _" q% L8 k# k+ A

' z# \" @" X/ ~. W9 n2 K

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

% n, Z/ g! r; B3 f, R

4 Q; B- y5 Q% i3 `4 G0 c# ]) ~: |

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

$ f0 T+ K, {6 }! T! A

, W% {& \& l3 f: F9 A" j

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

( C* J! h5 o5 j. S

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

% O9 @3 G% q: G4 X* ~& Y

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

5 G* `# o8 K( D) n* t7 K5 e) P

# Q3 I( b, K8 Y7 \& Q8 S% q7 ^

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

/ f5 S9 ?- f% c e; C! ^

9 l+ i, a1 [+ _; s8 i

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

& c [+ L D0 N D9 A1 O

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

$ \( i4 ?) i! I' n# Q

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

E3 @, {& w( a/ B

; P. Y4 J1 R. e

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

* M& |* O3 B. h' a C

% X8 V( V/ U* o! ]# ^

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

$ s V+ q8 f7 d8 z3 ?1 O

2 {# \: t- o4 J# l) C: p8 ?

---- GlobalAlloc(GHND,FileLength);

+ A% v: X. W- n6 G" `

% i. C1 {/ r5 o- U5 [2 [, E

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

& R+ g+ n% A3 W

1 Q% H( C. t8 Z

---- LoadFileToMemory( mpBitsSrc,mFileName);

- J' `9 W. N7 x+ v% y7 N

/ v1 p5 s1 ]; V+ `+ ]7 w

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

3 Z3 b) T0 A: H& b" \) A( E

4 C9 c8 t+ E0 w1 e

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

9 u' f( c) A) m$ v

5 i( l* }* x% l+ f( B3 Z

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

* |% y0 u. n- ]; r/ S- q

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

8 q% j/ q; U ~. T+ d5 Q- ~

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

" R3 d4 g# N# [8 y5 n

9 o8 F1 D, s& l k" l! [5 V

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

& X# u Q, p! Z3 Y& `& X

% O' ^* c9 ?0 s3 V

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

. y& M3 H8 `8 m) ^ [0 L& p9 G

6 g6 [1 A6 r# B) k7 \

HDRAWDIB m_hDrawDib; // 视频函数

- A2 Y! P" v/ T0 [

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

$ R- D! ^& ?4 a6 h, C

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

i) Y5 A" f4 i# w5 q+ q$ }

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

& K, j0 G6 S, ~3 k' R1 Y

f" R: K; L2 h9 n: V$ U1 g

- i) a& I$ i& E6 [1 m0 ~; e _

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

) n& P6 ? M3 ]( n

---- m_hDrawDib= DrawDibOpen();

# b7 }# R. r- O; c3 @+ H$ p9 W* q

: U4 U7 B ~3 _* `, @

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

' X, ?4 o- e- |8 |( n+ Z: U9 z5 N

d( h' q- {6 N4 M

if( m_hDrawDib != NULL)

. c0 R$ t, Z! N' g2 @3 a

{

# Z0 w5 u( [/ s$ ]0 H5 p- v+ X

DrawDibClose( m_hDrawDib);

4 U7 E1 f3 P" L

m_hDrawDib = NULL;

# J# S9 w J/ n4 I

}

) ?7 _& }9 i/ A+ f/ x X0 N% y

R/ K$ `" o5 l/ S9 g6 x, N1 D

p3 ?8 n+ Q6 e+ L1 _5 D' I

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

3 c. x# X- h4 ]+ F) A' ^1 Y7 ]/ U

voidCViewBitmap::OnPaint()

% S; `! n0 C% G. o( U

{

; o+ W2 P) G, z/ g0 U: f

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

+ j" \ l7 I3 s4 n# V5 Z, u: e, T

GraphicDraw( );

% ~2 P2 v$ g$ F$ p

}

9 E5 }3 z' P% k9 m

2 E4 I6 G9 Q8 O( o' H( u2 A& b' c

voidCViewBitmap::GraphicDraw( void )

8 C) o' P0 C& t7 L; q' v v N

{

7 I3 C3 N9 g; i* M7 J: G

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

+ o1 H' q# n6 k2 y7 \

BITMAPFILEHEADER *pBitmapFileHeader;

8 [, W- \3 e( d# F% r# y$ t% F; E

ULONG bfoffBits= 0;

' p' T9 N) a' y" v; Q3 a

CPoint Wid;

& K9 ^$ `0 h3 x3 z' n2 P; V/ v

9 c/ y" i" y% [4 c( [

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

% |3 ]: x0 ]" I) N! y+ _' M

if( mBitmapFileType < ID_BITMAP_BMP ) return;

# I+ Q2 A" [0 K/ J

" f, o! \; k j! f, c4 ^3 ?! K

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

9 a O0 K+ Q. W. t; y* B

// 准备显示真彩位图

( U# @1 i) q4 k( n/ `9 a! P

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

3 f7 Z$ j. N* S h

bfoffBits= pBitmapFileHeader->bfOffBits;

9 ]2 ^6 f3 C5 G& @4 ~

+ L; c8 b2 S0 K; r

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

6 K" ]( @" a3 ^# F: j

. V1 e2 g8 F6 \: {! _: \& H

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

4 {; P+ P& D3 D6 s' z

{

; ~; n# I# H: Q4 z2 J& x

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

0 w8 g$ f2 Q$ D) |+ A0 m

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

6 g2 F3 Z9 q; s

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

3 d& D" k* r: I) K/ B$ c

// 建立位图

F5 t8 w4 X$ K% a

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

7 b. \1 J0 j- j/ u; v1 J; u

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

- F3 n* L6 s Q7 E

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

E+ N; G; b- U5 M& C

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

# s% O9 e- M8 P; ]: v( L, J. b

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

0 o6 m* ~3 J* p/ r3 ~; N( t

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

! [. D, a+ y7 M/ p

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

5 {3 ~$ x1 N9 j6 b% x! h% F

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

9 y1 u* n! P- _9 |4 }5 w" d

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

7 T0 e! y5 _! ?) d

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

" B/ G9 h1 Y. A) V R

D4 X% m* B6 U% E; X$ u

if( mFullViewTog == 0)

- e7 l% b1 y6 O5 R" D0 X

{

5 e# \* f! v- M" O U. G. g' h1 g$ s

// 显示真彩位图

6 d# }( T0 Y' Q* V' G# X7 E

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

+ p- b& c, X* m9 r- F

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

" @* U" i& W x

} else {

3 @5 q; j7 o4 S" k) g% T5 v

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

9 C3 f* N$ K9 ]4 B

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

, f7 i& l, A8 f1 r) s/ J

>biHeight, SRCCOPY);

7 ?& L: @8 u4 c8 o1 e

}

! y! v0 U2 Z& o9 w+ _- s+ S5 C

// 结束显示真彩位图

2 O9 W" r# W$ I# K

:eleteObject(SelectObject(hMemDC,hBitmapOld));

; ~& t3 y4 I% n: _7 `8 z

// 删 除 位 图

; j1 S- c- y3 h; O9 e

} else {

5 |( f6 m$ M+ X3 o) Z7 b5 Z

3 t7 C7 m3 c; k& j

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

8 k- z. p! J. m. b( k

# _$ {3 V! V1 V$ q3 V8 O

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

- j/ j. h! k8 K" s6 L4 w' x& a$ w

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

4 [" K9 Z! f# `/ u6 m% h/ ?

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

$ q: E( e1 u5 e$ \& h$ R/ ]- V

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

# s" ~" ^& W2 ?1 ]1 W

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

7 T5 a; t: x6 x$ H" }

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

, n" f/ N+ u W( c. F1 M/ H, x

6 [* o. T! ^2 U( t5 u: o' m9 m* N

// 显示真彩位图

8 X. j* y& }. L- }- S! b8 E

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

; d4 a; P2 C! I4 z; B: X

8 f# r7 C9 O+ O7 E

if( mFullViewTog == 0)

2 N% v6 K9 z; Y3 c

{

) Z1 [& @( m9 g

Wid.x= mDispR.Width();

_0 A0 N9 o+ x u4 F

Wid.y= mDispR.Height();

; S/ R- t8 l1 m5 g& g6 Z

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

4 q- h- y+ k' C" e: J" o

if( Wid.x > mpBitmapInfo- >biWidth )

! M% I" }6 j ?" ^: A

Wid.x = mpBitmapInfo- >biWidth;

- T) ^6 s- r- s, d7 b$ D2 u

if( Wid.y > mpBitmapInfo- >biHeight)

4 l3 j7 |: B+ @# Z5 }

Wid.y = mpBitmapInfo- >biHeight;

/ p8 b$ e$ ` `8 R6 r; l1 W% }

3 w, x, {' ]0 b

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

6 V+ ~- a/ a$ U `6 [5 j

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

, U8 Q# g: r& ]8 J* J; F4 E+ T

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

3 v' j( X- D! [2 `" h6 \3 V0 m

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

* L* C5 [1 j- A% |% X) u5 R

} else {

* z' i- Y( _% k5 h# {! L3 z- V9 j& n

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

. n- S. u3 I/ S% I( v

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

& `* b$ m& b% m+ G- u3 v( s! Y

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

: }! x; \' a8 I L8 Y

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

( G! T% `5 F9 J, g a

DDF_BACKGROUNDPAL);

7 ]$ q5 {0 I6 z' l

}

# I, n5 i5 n- L4 k9 I S) H

}

. _( k" a9 f, `

return;

# Y. |6 ]" s2 c5 f; o

}

- g3 Z( m: t: o+ q. B) B

$ U) @- D. u( A

9 J. b! g. F) d' J, V

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

* w& A/ D/ w. D: m6 f& l

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

/ M8 J8 M. z' l9 C

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

" X' w% j7 M$ N. d

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

% I# O# S" x+ ]6 Y' a

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

" j& }0 [, n; [3 A- `) g2 l6 N: Z

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

/ q& k6 @ B* b' N2 d8 r) L

' O3 g) C4 b2 ]( S/ u0 i/ a/ D

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

?) ^3 L2 J' m* j& Z1 T! k! r

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

. r' y( J6 E7 [& f

! I4 L9 X) u: L

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

. e7 Z% O1 c+ q

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

: c4 X e3 O1 u% B9 {

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

+ R' B' H3 v, t6 C! a* ]8 V0 {* M

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

3 m" M m# W. E) O+ T1 c; f* [

。代码如下:

( e) c& B6 q" R7 \) {' Y% j

( m3 Z7 L- _6 f) A1 S3 [7 E6 ~

void CMainFrame::OnViewBitmap()

- s; U* v3 R7 c

{

0 L8 ]( e4 p. Q7 x0 H9 t/ b7 [

// TOD Add your command handler code here

! Y5 l& A8 C+ \+ `

CViewBitmap *pViewBitmap= NULL;

2 A Z% _! Q7 F

2 O( E+ J1 ]2 \! v3 L( h

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

' m0 {* N& }( c

pViewBitmap- >ShowWindow( TRUE);

# W$ f- S6 J/ K

}

4 M' c3 L' h1 E1 g* m

& C+ N% E2 [0 Q( R, B9 e

' t8 |1 f+ e: n8 p0 p% N

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

% D6 l+ J) |: H7 @$ R0 D' [$ h& R

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

# q' S9 ?3 J0 z' I' b6 V

0 P5 h8 `3 d. d+ Q9 h

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

, ^& R3 m5 s. z% E: _! V( A

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

5 l0 P. ?/ e- V! q4 Z- `4 @

2 C6 X j; P2 m! R; H, ?+ {% W

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

0 o u7 _7 _" Y! X% x" F8 y7 i

) ~; X1 x) K; U0 @1 g8 V) ~8 n% n) l

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

" P9 t5 {5 x3 m

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

0 K' N' q5 [# c; ?2 L) R

/ O' C- N+ [1 J8 {' G6 S

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

! q6 t2 D# A: ]& p8 }2 w

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

+ g9 r7 s4 A0 l% H5 Q Z. i. p

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

7 t! p+ `) |. m! N, Y7 {3 p2 _

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

0 }: i; g0 ]" u

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

8 ]6 r3 s+ Y. z: k

; L, p' r! q# \( s- x- Q1 o; z

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

9 e$ ^+ s! g% I: g7 B: {( j

就可以显示该位图。

8 L( N8 Z2 o! t2 g! `" {

5 j- N6 Z) m7 Y# m5 D0 Y+ o' `' U

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

* m, s2 M& p, I% [5 b W9 U- O( z- f

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

& _" W8 ?: l% a0 Z" x- @: f4 ?

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

3 D6 g* u# z j5 i2 g

真小,显示速度快。

9 C, Z5 J# W3 q2 c( ]5 {+ T n/ s

5 N% w5 Y$ G; D5 h$ q

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

! ?& y' @8 ?. Q# |. ^) z

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

! @. g6 [* Z6 p8 o! A" @ L

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

4 C8 I" d! q3 a" T8 v8 B

# k) x% @4 t7 R& O' O' }# }. X4 ?

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

8 E" \% k. k( R+ O5 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-10-18 08:55 , Processed in 0.608344 second(s), 51 queries .

回顶部