QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

! Y( j; j. y% w8 d7 M- @5 f! k8 ~% @

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

* e& n& T8 d% Y: C, \

张义云

* S5 I {8 u/ t- h/ J4 w8 s* s( J* ~

0 P; U5 ~4 N" D6 E# H d8 b$ Q, t! `* `

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

) }; p7 f* z4 m% d! I$ u+ Q

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

$ U. `( S) A. H2 A5 ^, p

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

8 H1 I! }) S L+ x( m( ]2 _4 R- d

- h! {( X$ R. Z! r7 g# p

---- 一、BMP文件结构

+ d6 ^- i5 y v: Z' M# Y

9 q8 V) a W1 [4 W# y

---- 1. BMP文件组成

7 z3 l* F" I0 |

# k& ~* x! d O/ u0 |

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

7 n0 t' z$ Q0 X% b9 i

/ P( s" b! y# ]/ B S+ S

---- 2. BMP文件头

8 d5 |1 S5 V4 X/ S! x

+ Z3 u+ q& K/ r' N- N

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

$ @7 D& X5 \: p, K$ u# @ p2 h) k' n

; l: g% B" O: s. @! {( k

1 x9 ~% q7 k. N, [: {

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

+ a! R- m9 Z( t0 v' j

@5 g5 T4 U9 y

typedef struct tagBITMAPFILEHEADER

' _& @4 N! Q: W* a1 o) \- b

{

' d8 y* p2 e! V( q, [

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

4 A4 I% @; ]( p

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

9 K0 S3 O8 Q- i- `, d3 t8 T0 h3 n

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

: g+ w& v/ T9 u$ A1 K

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

. L- l$ y( J5 V, @

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

X8 q/ `% C2 r

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

9 ^! G1 `& W3 I) w% s

} BITMAPFILEHEADER;

9 m9 p1 W& R8 Z$ w+ b$ a

' k! l" M7 M8 @6 a

8 T3 a. u# {1 g( ?* r: D8 Q+ T

---- 3. 位图信息头

- ~9 v2 H( k: h6 ?( |

----

- ?( _1 q6 w3 Q: Q6 \) ]9 H7 W

. d- e4 e( K8 t. u, P) Y$ ]

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

8 a5 u7 F; D r- Z5 E# E5 Z

typedef struct tagBITMAPINFOHEADER{

9 S: G% A) }8 x0 y

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

2 P$ N: e6 i- F1 K# y3 p/ A5 ?, p

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

: K8 g3 T g r

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

" d6 ]) T, t; W* n5 J

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

" g* c$ `/ h, E: t; z% u

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

" _* U5 d% @6 e, `+ C+ K

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

6 l$ ?8 W1 a J( P+ B

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

9 W/ ]' t8 s1 Q- K0 {; J

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

' K3 S5 b# y. _% V) p2 O& P

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

2 q1 ]$ s# A' Z6 \

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

8 n4 o9 b& V' [8 q

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

/ a+ @5 j2 x1 r( D2 g

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

5 r+ J+ U5 {4 S) M

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

2 g- d9 C0 ]5 X% g3 X3 r/ [

} BITMAPINFOHEADER;

. y j. j/ Q2 f2 d! M

+ Q! ^4 [. `' K+ h# }+ t

0 n% b; Y! y7 L$ Z

---- 4. 颜色表

; j$ Q2 N1 u2 ^# ?( K

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

( ]0 Q1 y8 l) h2 H7 h2 r

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

! M2 _0 v) Q; K5 V

& H& Z. z% L' N1 {

typedef struct tagRGBQUAD {

% z4 v z `* \; D' h7 G- D

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

8 `; ^2 K2 }9 h0 {. _ q

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

* X6 L% N, G- I5 P7 S8 C l" E

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

3 ^8 b3 e0 K1 @

BYTErgbReserved;// 保留,必须为0

+ w3 v# H" z+ w y" [

} RGBQUAD;

6 b* S/ h$ K" g$ a, z+ }

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

/ A6 f1 Z! d( M4 v3 W! \

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

4 r/ M! M% n# M# d& T

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

3 L( h; w: D# ~4 m3 n: P# ^

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

9 P( }( |0 G2 v, L$ f7 i' w

typedef struct tagBITMAPINFO {

6 h5 j4 K! n% w) `

BITMAPINFOHEADER bmiHeader; // 位图信息头

: {3 I% e4 z" ~" l( ^0 ]8 f# R. l

RGBQUAD bmiColors[1]; // 颜色表

- h% e) N: C' `+ T

} BITMAPINFO;

2 c' t6 N' X, ?7 n6 d( S

" i' ^% V2 M+ Z1 o; j. z

( y g; j" w5 M0 w

" q# d8 }2 s- f1 ~% S$ M8 v4 B

---- 5. 位图数据

$ q( `# L) `/ Z" }! C) \

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

8 C! |4 S' i/ ~) Z) v

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

; y) f, Y! j, M% R6 p; q2 x8 ~

% L4 k9 f, q( R0 j" c

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

2 v7 ]' @. Y6 \! t5 i+ P

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

' d( @4 _4 ^0 t2 N: { G! U

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

( U7 i( \9 ^' {

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

4 v% ^# x/ F7 e$ p

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

, s) e7 x7 V# |6 _7 t2 h1 d

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

' P3 E! l5 s6 e! N

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

5 q3 t. g6 j7 i( C" c! ]

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

q. k; ]6 X k3 C: I! u3 X0 v! X

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

) B) m/ ?* a ^, r( h) Q( F; C6 Y# h

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

5 g7 l* B5 g3 A! v9 Y# H0 s* S. Y

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

- K- S8 ]. Q# ]3 f$ s3 O

DataSize= DataSizePerLine* biHeight;

' t5 H" g- u8 Y8 D' ]) T

0 U. O5 {" Q& S: n% n! w

- V0 A3 `/ C9 n' w6 C8 O8 ]

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

0 B% M+ ^# r: \; a( B

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

8 X( Z @8 ?, N, e8 t% J

0 Y/ X/ a$ E+ a+ {6 D- i

---- GlobalAlloc(GHND,FileLength);

8 F& s9 t: g) k) `1 l2 {

, A+ ^# a( H' b/ L l

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

0 V& D9 H) r, w; v

6 J% W* `$ K) E) ?6 O7 b5 @

---- LoadFileToMemory( mpBitsSrc,mFileName);

9 K; Z( n @2 H. |, B

; ~9 b% Y) S% d" u

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

- v2 j+ l. L# J X9 H

9 M( ^! ~& m2 S! m# `9 o: D

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

& h( d9 B% r/ d; ?7 F( L; x- ~' g

DC,

) T: ]8 \: ] F+ H

9 ^% p+ A' p/ o0 p0 ]

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

$ k. n6 ~0 X. o5 ~1 r

1 o# o V. H2 N% O

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

r7 p% Z9 P) } \: T5 K$ Z

; ?, x9 J# z/ Y( Y! f+ I- A+ U

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

7 h8 _1 z- [& E

( q/ j" ~' v7 J) |! E/ j: e1 T& Z

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

) q' v5 c1 h% B; c' A1 j; C! l

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

* l+ l7 M: \& U

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

# T' @; k" Z$ o3 R9 w3 G

' _4 F& w! x2 a$ {

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

' | G* H5 K# S& K1 S! Z

( h4 @/ X. o B4 _% c( E

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

: }" h( ^# l! V, p8 ]- \

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

$ v t7 a+ i* Q. ]- A: H

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

, B' ?8 T% A) O3 K

: Q& ~: @4 `# B

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

4 E4 C0 e7 U3 \/ f

% A, z# \ p+ Z

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

$ u3 t' Z. D. z# h/ V. C/ P, g

$ j9 Q- P \6 {0 B6 J+ o {

---- GlobalAlloc(GHND,FileLength);

# F5 t5 K1 [. P( C: H$ H

% o% N [3 j# R% d( w

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

: v# W! `9 u! J. q( e. t5 d

% V( x7 j: Y* e9 |

---- LoadFileToMemory( mpBitsSrc,mFileName);

1 M" [. T5 j% i2 m1 B3 ?

+ P7 M$ x' N4 }: b

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

5 B; ?5 D% g X9 `' O; V3 ^; q& B

; l* |9 _: {8 g2 W* e; `

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

( O' d+ x6 \1 o7 t

) B9 C+ s" g, \. g. Y4 v& T7 U

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

- F7 |4 E0 r) j" q4 R0 q" j7 v

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

# f3 S2 F8 w- j$ s$ R1 a2 r. ]2 _

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

3 v* K' h$ k. H1 V4 A) T: M

* c9 a/ g9 ?. O' D5 L/ C

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

5 ]0 |- P$ B1 }: H5 y' d

0 c) C3 w' x% k2 X6 E" k

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

4 V" [) p3 z8 e4 m8 J

7 Z; B3 _0 G: @% {' n4 T/ |. s' e

HDRAWDIB m_hDrawDib; // 视频函数

0 [) P( e& L" |, X+ S) n; c

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

# U# k) c8 x7 @; v7 b7 z5 A

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

$ D8 b. C% v; |' D: |

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

4 Y# I8 [0 g' |4 {+ f

+ {4 n8 M6 A) y0 L) S5 k' C

* Z: ~6 W- l$ k0 h0 s! B0 w3 G* v# P3 `) @

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

4 t j* ]3 m7 j. L, _) B( }) Q: I4 `

---- m_hDrawDib= DrawDibOpen();

9 E, W6 p7 b3 x# B

6 p9 u7 M0 P+ B

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

. k7 d Z& p. s- ~2 V% \' S- U8 B3 |

1 d/ B) p0 D1 J) o8 b4 d0 s

if( m_hDrawDib != NULL)

G4 c* M5 G9 W* R5 Q% m- m3 _" t5 B

{

; ?5 L6 F; i- }: F" Q/ ^; q

DrawDibClose( m_hDrawDib);

& p& Q1 D4 ~3 | p* M( \9 L( t6 P

m_hDrawDib = NULL;

8 o' o9 p, X0 O' [0 o, N

}

; O3 b. W7 M% L. G f E5 I

) n# ]) R& R! A/ i1 t0 o' O8 [

1 Y% }. M2 }0 X6 R

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

) N4 T, |: u* E* _# A5 j

voidCViewBitmap::OnPaint()

! M% i) q, ?' }. U- l& N

{

7 w1 \- |( U$ J

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

1 t% S- @* [1 H2 D$ m* }8 \0 |) Y

GraphicDraw( );

* o* i' d4 p& r5 G& G9 }& A

}

! ~8 k: x) X& G+ ]

* A6 X/ D' }$ p' a% g

voidCViewBitmap::GraphicDraw( void )

) K4 x4 c8 m l

{

) u4 S: ^7 \9 P0 M/ {. c( Q0 `/ f

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

) ]% X6 G- o# a' G# r

BITMAPFILEHEADER *pBitmapFileHeader;

1 q* ~" }/ G, {0 X' `

ULONG bfoffBits= 0;

6 ~5 Y0 ^' H( o, `3 }

CPoint Wid;

9 {- j. n! Z0 \

& p! Z S' }# E) D! N/ y

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

/ a) J/ g& f& `8 D, _$ r% D

if( mBitmapFileType < ID_BITMAP_BMP ) return;

2 w* S- s, }. u" q4 J( x7 ?) F5 \

! H5 B0 a, d9 H$ j7 ~

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

' z7 h, p9 N1 n! x0 [4 T: y6 e! H

// 准备显示真彩位图

- Y6 Q5 G2 c/ w6 Z

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

# M, s3 M9 T; {" ?7 G7 |

bfoffBits= pBitmapFileHeader->bfOffBits;

( }; e3 `- H% U# s! v

0 c) p7 c( n4 U# _- @# a+ U

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

( C U! z5 W' v7 o

" @+ w. E2 J" D7 z; a8 e

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

$ }# i/ P5 [2 {' }

{

7 x& G, ^& }( G1 o

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

/ }' I( n( y" c( D2 s

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

6 d( K5 ?) t" {% e- {

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

" O; r/ K7 s7 `

// 建立位图

8 F4 n0 Y( b( \- i ?7 p3 h P7 v

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

4 N8 j6 x4 q# s( x& N% v5 G; | z

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

0 o$ w( i0 }6 T( C# Z' f5 k4 w$ a

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

3 p9 d; \) L P2 t( y1 O

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

8 F; k! u& A5 R/ Z

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

4 B5 N3 U# q% D3 [6 k

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

( W" ^0 o# N/ h% i

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

3 {3 X8 k6 @5 E

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

9 _6 z2 I; A1 ]. @4 L8 w8 L

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

0 {7 W5 j7 \8 J- x" V: p# N

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

2 j" y0 w: e, C

: g$ g: P$ ~. ^# b( S

if( mFullViewTog == 0)

. j, A1 Z3 R$ P( q; E' v: z4 t6 Y

{

4 x' @" e# d" |1 A, o

// 显示真彩位图

7 V: d& A2 _5 J9 c- x9 u, b

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

9 R' L3 Q2 m0 w1 [: }

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

- ]" V" J" F9 m X

} else {

; u# R. [3 V+ i- Q5 Y

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

' H$ \0 ~/ L4 `3 z- W% p: d4 H

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

) ] z5 c1 c6 g) F6 i- p

>biHeight, SRCCOPY);

* h$ M3 G) r" j% U

}

9 H9 u7 {! A. _; ?* n6 F Q

// 结束显示真彩位图

, n& t) Q+ Q* I3 R/ v

:eleteObject(SelectObject(hMemDC,hBitmapOld));

6 e; `2 p7 x/ t

// 删 除 位 图

, R; Z( M& P8 k ?7 g& L

} else {

5 \) d( \! x7 T; G2 ?! C+ ^

2 c0 ^ r- W# Z5 H, @

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

, U+ X: E$ i7 z5 i7 V

- W0 p9 j6 A% Q! X

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

7 m8 b: N, T0 ]7 [+ r0 s5 i5 ]6 @

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

+ |& A7 i, z2 g5 Z

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

) ^- A" n8 N0 B; a& S7 r: J0 g

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

% V& o, r7 Q% J1 a9 g4 L `

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

! }9 ?8 K5 r; g/ J& b% q

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

g4 o2 U# E0 N' F% A) g7 o- {. E

- ?' q8 k& q& w6 a3 `

// 显示真彩位图

. X" n2 O( f& g3 U x \; b

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

/ g5 V# D4 o) L# w+ T2 e

" o3 L& a" m0 d9 n% H

if( mFullViewTog == 0)

) {8 r$ @3 T* k1 U' P

{

1 I" B# f: b! p& p* d

Wid.x= mDispR.Width();

- M. r- b! o c2 r/ j. c/ E, l7 v

Wid.y= mDispR.Height();

# P, ^# W/ T6 D) Q

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

B; S. a- F* ?

if( Wid.x > mpBitmapInfo- >biWidth )

7 l& g* x2 f8 L$ t& o% q' o* L

Wid.x = mpBitmapInfo- >biWidth;

7 ^3 {8 E8 Y" s# v0 G, y

if( Wid.y > mpBitmapInfo- >biHeight)

" ~* |: L# z9 c2 m2 d6 W

Wid.y = mpBitmapInfo- >biHeight;

8 t' n3 G3 I) ]$ g6 R Z# u& J) |

4 ?7 Q' k* V s( j% y7 ~; L5 o9 T

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

& ^+ V: Y0 p4 ^- _/ i

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

& S0 w `, I. ^# e' n

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

3 f' B+ A( |# a3 C& B

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

( w. s6 ?* u9 D' m2 ?8 ~; _3 C) G

} else {

8 w3 J, k* W8 J7 k" [- _

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

4 K: B0 z5 v8 T2 I! G

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

( l" T" S# c0 w4 e

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

2 e7 w7 w# e- t1 l4 p

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

' ?& z7 |% k9 l% L* H

DDF_BACKGROUNDPAL);

" K3 K ], r/ U+ x6 h# @( ~( I

}

) W* z6 g: ^3 R2 t) `9 [

}

3 D/ p5 N, P; t

return;

$ K6 q" _ r5 { j# D A

}

" }* v2 k4 F, Y8 I& w/ O

6 g2 ?& h1 @. @' e5 P( c

1 @# j# A O p) w2 h+ j2 Y x {& n

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

# R7 G, E* W! Q4 B0 Y

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

: t+ c6 @3 g8 G

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

' C( ?' Y4 |- F' U+ A. b

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

0 D$ I6 s+ Z9 L8 h/ ]' t. w

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

+ }7 L8 [; }6 O, m r, |

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

( ^5 l# K; D7 y4 w2 }; V' a

5 |6 I2 A9 l2 L

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

) E$ x5 H, @; f6 {

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

% i$ m8 K% q) p# P% ~& O

% p' {, P9 j1 Y- e

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

4 K$ W5 Y# Y( C. @' D& z3 S7 } t

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

* X3 s6 Y* g. \: i- H& B1 A

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

! j3 _2 R1 |4 R2 D1 D& h/ x h

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

4 o1 N' b, G# |+ r: Z. u

。代码如下:

1 f8 ]/ w" q/ p8 e# a

, p( P* q7 h. o/ h& F5 P

void CMainFrame::OnViewBitmap()

& r/ u$ P+ B2 [+ S$ |$ l

{

$ D0 ?4 L' w& @, k

// TOD Add your command handler code here

) N/ K8 ~4 _: ^% f! z4 A

CViewBitmap *pViewBitmap= NULL;

" p4 E$ f- W }1 I0 N- A

8 n. d6 Z7 b. U; p* ~* u

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

' O' _$ }0 n( _4 O$ {* [% i& Z& f

pViewBitmap- >ShowWindow( TRUE);

# W! f. t% _; j9 B0 W

}

& t( s1 o: `$ c

% A0 I8 t- T+ V! l# ?& c

0 v9 t& K9 R J/ D( g. T8 `

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

& D8 G7 s6 J5 c

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

. n" N% U) B+ x. x. t& }5 g) ]! e5 i

8 \0 M, G- x; a0 e9 L0 G! n

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

. g. R$ M; D$ `2 T0 c( L

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

2 z9 x X6 N! U' p2 h

; ^8 z# w: b! n, ?. D+ R3 g/ a# }

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

0 ?, ~- F2 h4 k4 l( ]1 {

5 W' p( w% {5 B) G( K t

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

1 A' a2 G2 w, d( m

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

, I0 a4 K7 J2 X: k( S" t

9 {, w% J# w) F0 A2 P

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

- H$ j R' I# v/ o7 {' g/ W

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

! a2 w% l8 X7 }: Y) T6 h, c. Y

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

! `- R x, W& o: C* }! p* L- c

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

2 d1 ~3 I' Y3 [

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

7 |0 f4 Z- s6 ]+ c

! B% Y0 D& I* ]# t* A

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

- g) f* W0 U! S7 ~9 t9 u) T

就可以显示该位图。

$ D' m! Q1 O" F5 M8 S# v$ f- e

1 h$ A, S* u' U$ b1 y2 C& i/ S

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

_# } b6 o2 m+ q( r/ l0 z6 E2 W# g4 i7 _

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

: D; P* c5 Q, S7 p

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

1 ~3 A `$ q3 [. F+ a

真小,显示速度快。

, l8 `) _6 C3 j( k. `. _' ?

( V# C1 e* w# K9 ^

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

' W4 T1 g. u# i; t2 O |7 _

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

9 h8 V+ ?. \3 a9 k/ R* ^

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

1 @. |4 p) {2 _$ N6 ~! O* \. l

; j5 n L4 p' i. l6 \4 g

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

2 F0 j( p, t ~& u5 A$ R' E7 t* g% C

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

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-10 22:21 , Processed in 0.285404 second(s), 52 queries .

回顶部