QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

3 c. n( j) ~/ _- g9 ?& H1 ]

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

. Q9 o Y; M' F7 l7 h3 k i/ G

张义云

9 n" B+ l0 a8 ^

6 Z6 M' J" ]* ~

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

5 X9 ^, ^" s) k5 P

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

& t; O' G ?& K* a; f: V V I8 w

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

8 n2 |* j: C3 M" Q

" ]+ z x9 G" B+ r: y

---- 一、BMP文件结构

2 v9 T9 l! z' G" D5 A

' C+ y0 l; y0 ^

---- 1. BMP文件组成

, k7 h9 f* b: } }. d

! m8 r9 D7 }7 i4 ?! w2 y

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

6 ~) Z* f; b) J" m, O. `! y

% Q' G! B( P+ J k9 _3 }5 T3 A2 d

---- 2. BMP文件头

$ L8 _1 F+ @! f9 E/ N s" h

! O K0 ?9 a1 v, K

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

% M5 o; @6 W/ @

% L& H5 q! l2 R& t' { \7 W* x

A! T& ^ {$ u: J

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

3 q3 d& F' C8 w% }. M

8 l" q, Q3 G' x( D" Y5 v/ J

typedef struct tagBITMAPFILEHEADER

6 C. p7 F* @7 i! r

{

/ C, a6 }% f5 w4 W7 ~

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

0 I6 F' I% H5 c: D) o

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

. w2 X7 ^, E; b+ _9 z2 ?

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

$ U; X+ O/ p# i/ O+ E8 e+ \

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

1 M" K+ u+ v6 K# m1 C

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

& ]+ |8 Y3 |# z, ?9 t/ s$ s

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

8 f0 N) q" v& u- f

} BITMAPFILEHEADER;

% G q0 [/ @+ I! G$ X4 ~

! j) F% G; h; y. J: m1 j, M

4 @' r: M/ C2 n5 M k' H

---- 3. 位图信息头

% z [( k W2 O' G7 c5 Q1 C( P

----

4 }# W6 @- N7 p* F

4 N* C/ `$ U1 B0 S

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

2 \7 B1 t0 t0 B% ]

typedef struct tagBITMAPINFOHEADER{

1 O2 |" g; p9 E

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

! a6 Y3 W) `6 W' x

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

+ L J% c4 h, K/ I D7 E

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

. ?' `! T! s% q4 ]: h" C

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

2 p& i t* _* G( h, u) W9 B( \; y

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

. Q1 p9 [# p: x; B9 `: d( F

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

( r" \3 ], U$ P8 c( L1 x

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

# Y* B2 o1 c6 H: W* ^ ]: ]8 U

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

9 X" P1 C6 N$ C) k6 k5 V

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

, w5 Q) b4 `, `$ T. |# l, v6 ]; a

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

; B6 a0 D0 v7 G3 k( g2 d5 K7 c

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

: E1 j: o% W/ X8 F

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

4 S( \( l8 Y- K9 ]

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

# v+ f. L* e; ~2 f0 i5 `! |2 |

} BITMAPINFOHEADER;

: ^4 y( S+ Z! ?0 d: P

3 x3 W: c- m* M

) h0 R1 F- r1 \! p

---- 4. 颜色表

, Z4 A9 A% q% [

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

) w+ P% X$ f1 s4 R4 x8 x1 C

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

7 G+ V7 X" \" A% K

: h, M- h: C3 i6 J1 N. h. [

typedef struct tagRGBQUAD {

1 j4 x B- h# D5 Q

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

, r# U& d6 ^. y& g: E5 {. T

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

9 M1 o# s0 H! @5 X5 v6 K

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

' ?; W( c. h" l, j- T

BYTErgbReserved;// 保留,必须为0

5 ]6 O1 j' M: U) L( O+ L& |4 g* N

} RGBQUAD;

" z; @$ V7 E0 R, i, t- I

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

/ I) g, t8 g/ o1 z, r' s2 `

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

7 z; m7 I8 j& a8 h& Z, J

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

, S' C6 L" h2 Z6 D- E) [9 c

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

% T6 m9 c n/ o0 f* p5 _. F

typedef struct tagBITMAPINFO {

! m1 x2 J$ G' I; Q3 A: Y/ g

BITMAPINFOHEADER bmiHeader; // 位图信息头

P6 `0 y+ X# e+ w( ^6 g+ c

RGBQUAD bmiColors[1]; // 颜色表

5 _# n/ P1 x" T) X0 S1 ]* h

} BITMAPINFO;

4 _! q, ?" F( B# m* B& @9 p

# ^( L! [7 A. ?/ _3 v

2 _. \" v" k7 u2 k4 _

E5 o' ^0 }" w& A4 o

---- 5. 位图数据

& R+ {. l- L* c# c- P# u* E' m1 E

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

4 p; ?; ?5 I1 |: U+ g

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

1 P) z8 n5 y3 n$ h" L: B

O' O+ F9 h; P* X; Y

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

0 e$ m S/ ?# Q1 \8 M

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

" q8 K6 C5 U/ q: n# A% P/ @

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

( i8 e; v4 v4 }# v9 i5 }( R0 M

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

9 {4 N" ]6 \1 H, h0 Y* z/ K |

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

! T6 b3 n: {& f6 U

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

- h* h$ j1 ?$ S0 t

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

# I. D) w0 V9 j4 ~' B5 b4 E, D

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

2 u* J$ F+ v. M8 v O

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

; i$ S8 W9 g6 [4 `- T; T" A

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

2 i g$ y/ G/ U7 M# T! A* @

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

% N( x8 t+ {! s! _7 Y' K

DataSize= DataSizePerLine* biHeight;

5 B' ?2 r" f* t

: ]! u: u3 d4 p1 z

/ @ t8 X c7 l% [8 u" z

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

+ w7 e+ p, o& w7 w% a4 {, ~8 b

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

! y1 {2 T3 n2 m

+ S9 v5 C- N' c( U9 a1 y

---- GlobalAlloc(GHND,FileLength);

8 |, d% v/ P+ J# M. m, w) T( s

- L& ^# B# w; @7 f: {

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

) f% A% k- K* Y& d9 P' g

7 H1 F5 j7 u L3 u# U

---- LoadFileToMemory( mpBitsSrc,mFileName);

! B* P) o6 |1 T: {- u: u

% |1 j+ a' k* E7 X; L5 D2 W

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

) H1 J7 |/ e; S' ^. n

2 V" h% J) S0 s1 E) q% x, G

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

7 e K+ ]* ~" Y( J1 f

DC,

( i& W% M& f! Z& [' n5 p$ K; P

$ x5 y" }( d3 {# u1 z3 J! B

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

0 s. @& o$ W6 k6 Z% w

6 Q* B6 H+ W6 r) m

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

/ t9 `; [5 ?8 [4 w1 S) U, k% V

! E$ x3 r& a& _6 ^

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

" C8 U8 G8 {1 ^& `' F* R

1 L0 ]+ ^8 T8 K7 J$ n% c

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

* l' m% _; N. f1 o3 F

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

( a/ r! J8 t3 F$ x& l

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

' _* B( e6 C" g$ v7 R( x

, ?0 y' d. q1 y

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

' O$ [! D7 Z6 c. u: d5 ~$ z

" `" Z& t: @" w! B, g! M1 \! l5 P

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

# G, g2 Z, L- M4 L

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

& ?# v$ p6 v- D, ?3 }' ?/ N

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

' ]" V& p5 h: l) {8 ?

r: h4 W+ g4 l

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

/ N7 D8 a2 b: B6 E% R4 }

# B$ _, m6 l& h) x. ^" G

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

& T) \( D" A$ O: L

$ M6 H: x4 q, t

---- GlobalAlloc(GHND,FileLength);

- ~. N0 f8 \( m( f4 K

{) ?' E( V8 G. B5 ^$ s1 L+ X

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

. H2 h7 c' X- e6 C

3 p4 N# g1 i/ T/ F6 l

---- LoadFileToMemory( mpBitsSrc,mFileName);

5 a4 E9 n1 p8 {9 ~) u

/ J* \* K$ F$ i% D

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

' F7 H: u( y3 ^$ X3 i8 P

+ R5 [# W. B1 J$ ?( M# e1 J! d- O+ n

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

, ]1 p" M# Z3 _: Q

9 k7 E: ]8 \/ H r( N V( F

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

+ l" P/ ^" q! A( h

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

$ d& P% d* F8 F; `' A2 b1 V( ]

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

5 p4 k# p1 D6 \: W% P* |! m. X

$ ]; s! @$ C" p/ D) U# Q4 b4 [

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

7 h1 m+ p4 J) N

! S H A- x) X* P' P5 M' u

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

. f9 H# g. M1 ], m0 X

* E7 o$ C8 r7 X# S8 G

HDRAWDIB m_hDrawDib; // 视频函数

/ {( I$ R5 Q1 S; N

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

: D6 L3 Q2 a0 K' y* {, t# h

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

" T( U" u* n$ k: P- ?

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

' O. \; i |2 g% L5 H1 S' U/ `7 O

* ~- `6 f) @# i4 t9 e

3 h0 c' r2 W/ U

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

7 ]' K1 W8 G2 P! L1 V a

---- m_hDrawDib= DrawDibOpen();

# z2 h9 \ K& Z" w4 ?1 @' N

8 F! }9 \+ X+ _+ e! K a4 ^* X `9 ]* k

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

. ^/ e( V p+ O" l4 t) V) y1 l

8 u0 v: D, C$ R

if( m_hDrawDib != NULL)

6 B, }$ K8 v5 ]$ k

{

4 J- p1 [/ x8 v

DrawDibClose( m_hDrawDib);

4 C8 `& a& J- \! ~8 _ p

m_hDrawDib = NULL;

( k6 R( b1 B% C8 j) {0 p# g% X

}

( @& k. s( Q+ b- X5 W

Y3 g9 d/ P: k4 P; W+ _

& `0 T M" H/ E

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

" ]2 m1 N. o, \' P2 t3 S) q! E- G

voidCViewBitmap::OnPaint()

: R$ V0 @+ l5 `; s

{

) y0 ~& E# Y! @- [! G! N& ^

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

+ [0 Z0 `2 x9 \$ l2 F$ T7 l

GraphicDraw( );

8 V( O$ r6 E$ A7 W5 d

}

5 {3 T7 {' h7 f" ^: c

3 n8 Z+ o% h( {* X# J. x

voidCViewBitmap::GraphicDraw( void )

/ Z ~0 b( F% N e: _6 e; E

{

2 O' g2 A8 g2 g4 }6 t* u* y

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

& M* }3 `) H- V6 p

BITMAPFILEHEADER *pBitmapFileHeader;

4 J; H" P+ G9 e. D+ ^% p1 ?. S

ULONG bfoffBits= 0;

# f8 I5 q2 V$ n/ E2 w

CPoint Wid;

$ r; d9 j" i* a& m* `

% g1 [9 |/ N7 b# X# Z) ]

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

. b& L- X" f3 {0 Y- m3 a

if( mBitmapFileType < ID_BITMAP_BMP ) return;

" S) W) Y+ A" m

8 A) G* H N1 N- H7 D& ?+ o! s

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

$ _2 R/ N/ j8 S

// 准备显示真彩位图

' P& c. p/ e! p0 y) [

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

% ]# w1 ]9 [, ^' i w7 A3 p

bfoffBits= pBitmapFileHeader->bfOffBits;

; _* T" y0 d% w( M/ I' L

0 O8 P$ j2 X* m: S: G8 J# m1 _' [

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

/ ]3 n R" C! \: ^

# l! o' g+ P# ~# \5 J+ W$ a0 p

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

6 {- ]5 Q$ l u- p

{

. G& m& t' I0 T' G# b! ~) c

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

. n$ [0 O2 z# l* t1 b

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

5 m/ O$ a: L. P, I: _0 w# g& G$ V4 T

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

: K7 d9 U3 p: \% w% I

// 建立位图

]# R. Y6 U+ A% g! ^) S5 G% Q

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

2 U2 s$ z5 |8 b9 i

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

9 v" G+ ]: v, ?( ]' v

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

( l. F6 k5 D' C4 O

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

* s m/ r9 o4 b: s; t+ a' r

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

3 N' @2 y$ l# i. _2 K0 P6 w( P- x

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

- g4 s8 Y N8 I- \2 c+ W# E+ Q

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

' J+ t6 P/ C/ r6 _

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

! `2 d3 H+ b; u* @0 N

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

, R |" q3 o6 N' `! }6 O( l$ \

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

& [( f/ _* g7 O; ]

l" h5 t, X# H) K) Z9 P% O) k* H

if( mFullViewTog == 0)

. |. C! n2 i, g7 |; J0 H

{

8 d% O3 d+ X( i7 I/ ~

// 显示真彩位图

3 `8 P: I7 H* l/ t% e; A

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

- _% U; g( M% R7 k) T

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

2 I) q# ~# Y; \& G: e* [- c7 x

} else {

1 M8 D( h/ t g, D8 O

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

" @# d1 ]3 W9 t$ T

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

' L9 X, a7 J1 D0 i- s. S

>biHeight, SRCCOPY);

. A- [" h3 p# H) t; d8 t v5 `" K

}

# l+ V5 |" z0 ~. C* @; e

// 结束显示真彩位图

7 ]( E: d2 C8 t) [4 c

:eleteObject(SelectObject(hMemDC,hBitmapOld));

, Y2 j& M9 J6 n3 b4 E

// 删 除 位 图

" s3 |! o* Y# p; M0 E

} else {

- G7 _3 U% S& d, ]" S% G. P

: }6 j f7 ~! \" X8 P$ T' p# v

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

9 a/ E+ P8 k# {7 C6 M

& [7 t$ N. x9 w& g2 i$ I

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

9 l5 H0 x6 F1 E* Z$ M

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

* M: W* G0 A: L5 s; }

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

( v6 S- d1 x2 [4 `, n3 [) j

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

6 }! g. l! Q/ |4 t8 {- v3 a2 K! w

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

' k* f3 M* R1 J- ^9 A

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

; ~- l8 w8 \+ v* O- F* i* r

% d V4 Q; @9 @7 h% f

// 显示真彩位图

+ m: S/ r! B8 n4 x+ w; O: q* ^* b

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

% ^ [( R* b# X& W5 E# i

+ O$ P) a, o, C) w8 x! ]

if( mFullViewTog == 0)

; g' ]4 a4 O- Q; R

{

: u1 @ c% t* D6 ?8 P

Wid.x= mDispR.Width();

9 |# `6 H# v' t; [

Wid.y= mDispR.Height();

. l' o) m3 ~2 i' a

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

1 s& D* q( Z+ m

if( Wid.x > mpBitmapInfo- >biWidth )

8 h2 }5 r0 p% ?6 m: T; m$ M" G

Wid.x = mpBitmapInfo- >biWidth;

" V- [. [- H k* d S

if( Wid.y > mpBitmapInfo- >biHeight)

( E6 Y5 f( ]5 ^

Wid.y = mpBitmapInfo- >biHeight;

# f8 p0 } L, I( R

2 R" m/ B! j- c4 @( l) Y1 q

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

& y9 N' i' w( l7 z1 [4 k1 B8 J

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

' u2 v( w' [9 L& q1 |. M

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

+ k! n% f3 G4 c0 I" e1 r9 }" F

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

7 O! D) }; b, O9 m

} else {

1 ?4 L6 s) } {/ T

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

$ a8 Q- X( D4 E6 Q. F

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

. S9 W+ l2 `7 o* ]/ U9 v$ X

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

) U: h* q6 Q) g" J4 R

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

2 e, k6 R0 I) w, l# q/ |

DDF_BACKGROUNDPAL);

8 j9 Y. Q4 M8 G3 V3 V, |6 O. n

}

# c0 Q- a4 P' t: p

}

5 F4 X4 C3 G6 m2 q3 ^ C

return;

' z6 g; P' G2 v$ V$ V

}

" S3 i! c7 \8 v% p- K1 P; H

7 y$ s' v/ }. U

* c( z7 W- ^8 v) m6 y+ T

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

9 t4 D: ]& j" ]* X4 c+ z! H

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

& R' Q' z6 X6 {9 K, |

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

" n5 s# K8 g) \$ j/ ?+ Q

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

; I& x) `* t- ] R

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

7 {' s' `: O9 v4 @) D H; U7 t

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

5 K" I/ }4 O8 E

3 M2 _' l, m; p' d% u) `

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

* i( U/ B8 l, G# a

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

( H* J" O- F* A( D5 a0 v: {8 w1 R

5 p6 L! g% [3 c! j

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

: j3 h* y% |( v7 X1 T7 H: |, k, V

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

4 [; y* z! K. S$ `# K8 `

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

1 Q: m4 r0 `! G: o+ d5 t3 E

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

+ X3 u ]0 L4 C% U% b8 g

。代码如下:

6 m, z+ t: Z! S' a8 L! u2 R

3 O# U" w: G9 X2 b1 x4 D

void CMainFrame::OnViewBitmap()

1 q& V% Y- S1 k$ C

{

1 G1 M; D/ p6 A; X! G; a

// TOD Add your command handler code here

) w% E) m6 @+ g

CViewBitmap *pViewBitmap= NULL;

4 _7 p7 Q; Q3 i9 E8 k# G. _

+ U2 I% [( ?! q( ~

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

. m8 A% {; y# [

pViewBitmap- >ShowWindow( TRUE);

9 _/ x/ C% M. K+ ?3 v. z

}

) K; y4 T$ r7 ~) A8 M) S$ }% q

( Z7 v6 n9 |0 B

! W% w" G, r0 L7 Q: a% w

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

; [9 Q$ `7 Q0 ` u

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

" H& R8 H$ S. T

4 }: ~+ f$ q% m# [+ [% d, r0 v/ ]7 M

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

* c9 k9 R3 q( {$ x8 P2 e' i( R4 y

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

1 c8 k8 }) G) T1 W) p+ J! S

% O+ H" O0 r: }; P

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

* U) X% K" P, m1 \' m' o

s1 A! e4 j* H8 t0 M

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

3 l; E* t2 q$ u0 @2 P+ {

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

/ ?- X% h4 G( g5 `4 g" Y4 F

5 a" P: x: U) f9 y0 t

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

& F3 a7 {. M, O2 D$ e+ }

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

: U C) n0 q/ n. b7 j, S

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

0 v D* _7 R" F) F1 T# E. z) p

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

9 U% F9 w+ w* ]6 N! J, u

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

" s4 i+ Q1 q* s1 Z' P: Z

/ g1 R) N, U+ Q& j1 u+ t; F( j! [9 |

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

7 A( s" A) G3 p u1 \% t% D9 D

就可以显示该位图。

+ G3 f1 x8 G3 |! O- N6 ]" m! d

2 {+ E, M- d+ }3 |# J$ L1 A

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

& l- }2 C( O" d! I* U- g8 [' V7 l- |

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

& V: G$ a) i, o5 C( I, ~4 Z4 p+ M

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

, ^1 R4 L" M6 M; ]# \. u: {" N) t

真小,显示速度快。

* N f( R* M7 E, D# X; r3 D2 ^

, K' }, [8 P' P3 i

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

" h8 S' h% c- O' R

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

, J% h# f4 ]7 `6 U- U( [ A

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

4 O C8 v. X) U$ m( s4 A

3 }) C5 c+ ^: D$ {/ m

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

* w5 U. v+ Y2 i7 \

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

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 02:44 , Processed in 0.423347 second(s), 59 queries .

回顶部