QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

* s* Y3 m3 T+ c4 s7 U" V

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

. e! {' J9 \: V" N. f: i

张义云

4 V9 q8 ?( @1 u

4 R+ r. O9 }/ ?! [, A1 x2 O$ w" t

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

9 T: c: w" b) Q+ U# p

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

/ b0 c4 Y- ~' n

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

! q6 f" k* f0 g. w( k }

* l* B+ H+ N, b5 G# y" o6 N

---- 一、BMP文件结构

& t" A: g5 I0 ~% Y9 U2 m, E

& c+ Y# B! O" a( _

---- 1. BMP文件组成

( L# w/ U3 b3 C

/ H$ g4 p* @5 a* K4 ]: X

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

" E3 M. p3 R# h5 F. G) c

! o- f* k/ h. l" @& i0 J

---- 2. BMP文件头

3 O2 B" @, K, ~3 k* `

+ s' j1 @' i8 i6 S; l

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

& K# L+ ?9 J9 g- J

! E( W8 ? J2 q. q/ A

* x, q9 i3 Y: |. N8 O( r

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

6 A$ l7 l8 Y; G/ B" Q! v

- E9 m8 O, P; N2 V7 L3 B- v8 g- Z

typedef struct tagBITMAPFILEHEADER

" P3 {1 u9 Q5 n; A* `' c9 s W

{

; {. w) s* a1 Z: A2 q# \ i

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

' H+ G9 W1 x6 S+ b6 u) a" e

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

7 b, Y7 p: B5 w7 D6 m6 ^

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

* u( @! h3 L! H" j$ s6 m) M1 y: {

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

" B, p3 w* M% d1 t$ {2 z2 ~. @

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

+ M" J% w, U+ ]7 l; x/ Z: c

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

4 [* `2 u! J4 w+ K$ y: }

} BITMAPFILEHEADER;

* ]' r8 \0 d1 _7 \3 i; X2 j

' j7 D, s4 \/ k9 H' }! z

/ S+ A$ U9 \7 J

---- 3. 位图信息头

9 V. a; z7 m+ B* |

----

4 }& `2 D/ c7 p4 N& @& `- \; ]' ~

7 J/ y0 _/ z7 E/ s, C( w( A' Y

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

6 u3 s" H/ j4 d, V

typedef struct tagBITMAPINFOHEADER{

' q7 J9 q, k+ c" K. r* ]& i

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

! n$ x9 i" r9 n6 v2 ^

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

4 T9 _- P6 t4 W% }$ F G

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

( M5 y [8 O% z7 Q3 V+ g1 v

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

! v0 m7 R8 y9 x' v+ D S+ y& E

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

, Y. ^2 _% B" B2 z: D6 [

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

; i4 h1 X$ P8 N1 ~

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

6 {+ Y! P- o! X, f8 W( @$ b

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

- r) j' `1 `% o1 T: X+ D

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

( E: g5 [& X* h! [" `

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

# p! _) v5 T+ J- [8 o4 ~: @3 V* [

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

0 }3 W% Z/ H6 t9 w1 S2 e |& H

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

9 r2 Y5 }( U& M3 N5 {6 i0 K' H

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

0 m* B" @5 _% j0 R5 |4 @) j

} BITMAPINFOHEADER;

! N5 E7 S& T9 u* o4 p

^ H7 |; l; N8 \1 K1 N" e

M8 X! w2 A! f l+ K% s9 d" K0 @( N

---- 4. 颜色表

1 Q k1 {' O3 a; A4 n5 J! B. O

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

4 g! [! a2 U+ h( x

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

k, C; n6 W# z0 G

' Q( F% _( E/ D2 o: ?! d0 [' F

typedef struct tagRGBQUAD {

' f W5 c$ \5 e9 t2 _8 W; m9 o

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

/ P) i( ]8 q. {4 u4 |

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

" t7 b# }2 e! n% h) S3 y! ~

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

7 c! H* D j M, M1 i, W

BYTErgbReserved;// 保留,必须为0

3 n* ]+ ]. A6 w

} RGBQUAD;

4 c9 R7 l3 N5 ~7 z

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

( ?7 ?& y- D. |# i" x0 ~6 a0 }

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

# U( _4 o: i4 O/ d3 O

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

4 d- z0 g9 {' |

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

& C8 x1 x2 ^: K6 _$ o- ^% p1 n

typedef struct tagBITMAPINFO {

% u% T1 s" u: v1 ]7 K1 d% V# P6 Q2 M+ R

BITMAPINFOHEADER bmiHeader; // 位图信息头

3 f1 X: _# K. v

RGBQUAD bmiColors[1]; // 颜色表

$ M8 D$ P! H/ ^* {5 Q

} BITMAPINFO;

, H' ~9 s3 E3 J% i: K) j2 |* A

$ {! d% I" y/ O. J

& u$ h# G) X6 j8 z8 k( z

" D& a$ z7 A( z# k- A3 H' N; }

---- 5. 位图数据

, H0 ^9 U! A# w/ T4 M

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

( @+ o4 n" y- N0 {& H0 r6 [( ]3 `) C

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

|( q% w& o% M4 U" F, s- r3 g2 T

% v- }7 f! H- |. V; N7 g, v. x

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

: h7 G7 t8 M+ F* ]% F9 L

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

# Z0 d. @5 w& F/ S. G( @

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

5 [: p7 u' A- M/ E

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

. A& b, N% G/ n

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

1 Z1 _ G; e5 x4 c

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

3 X5 w7 c9 A% m+ x

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

: A! G$ A6 K- D5 @( t

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

& ` p9 V" g+ C( J

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

- A. M' k$ D1 p% u) W% b4 E

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

1 K0 p5 L2 Q/ l' E' W2 D4 D! W; Q

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

7 h6 G. H/ j# N

DataSize= DataSizePerLine* biHeight;

v8 ?9 l. ?$ l) Q) K1 ~" c$ U

, T; }" R6 B$ }4 A" Q9 v T

0 R' ^0 u8 {7 h% y* ]

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

. J& ?2 u* [+ H- t2 m7 _

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

: P6 {2 e2 \/ ^

3 t% i. ~/ u* L( D9 J7 C9 d1 f& o5 C! ^& L+ B

---- GlobalAlloc(GHND,FileLength);

3 y3 `% l, {# x) r, l; C

% R( {$ ~6 E: l

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

8 s, s6 T1 o8 D2 M3 k" l

6 q& Y! D5 Q2 b0 }$ ?" ?. U. V

---- LoadFileToMemory( mpBitsSrc,mFileName);

- B7 e+ m& `% j U! ~. Z& U

/ w) U" w+ {4 h1 |1 |7 P/ {: e

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

- q/ ?1 w, t l5 ?. I' K5 N

) z* d! f8 P' Q& i G9 E2 f/ M6 G

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

7 V6 Y" k: z7 {% h% t

DC,

8 P& G+ ^/ g* a' c

. f( A. V; z9 a2 i: \7 `7 t; y

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

5 Y( w4 L% c6 X; y6 I% D

& t4 z$ P0 b" n" c8 q3 d# `( z

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

7 }& x: H) f7 ~7 j3 p1 j

* } [- `7 Z% D4 w' }0 h5 x: v4 H/ `

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

) }. v: {8 V; j' k' [/ E

2 p1 ~/ Q: I; Y6 a/ }0 B

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

4 l2 R$ Y Z4 w" I6 ?; _# Z

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

9 U |! @; n* x# c9 l/ A

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

& `. @& C; v) [

! D2 w5 f4 _" v7 d$ \5 N3 c% K1 M# w2 c

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

. S1 R: L* S: B; w0 \

1 l1 o& b( ] f V$ \" K. {: \2 y

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

: v/ {4 h: E0 [1 x( H6 f

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

0 i& L* S" K$ y$ C4 K2 X7 v$ s3 M

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

! i2 u- f: M! |; w2 I

2 ~1 Z& w' o l, o" \1 T

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

+ F; B0 g" J9 f* a

) ^; F2 G8 S/ k0 X6 ^

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

; d8 _+ }5 [/ M2 o$ Z% }

& |( Z& J" c& D! R5 g* o* x2 W( @

---- GlobalAlloc(GHND,FileLength);

: a( v, R4 O9 f/ d

; r6 Y8 e! y, {

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

$ b7 U3 J6 b' }+ c3 ^. F

% V1 o$ M. {9 x' d0 t+ E2 ?+ _

---- LoadFileToMemory( mpBitsSrc,mFileName);

/ H" z! A" z t

+ I N2 C5 H: o" O

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

+ L2 q% A! Z$ F) l' d

! h1 ^0 z7 D) n1 F R. b* C$ R/ v

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

; V+ L* L0 T' X( A

! _) C! K2 [! _+ C2 ]! A% A* s

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

+ j& X" X' Z1 d/ x! L

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

) ?5 h7 u$ W) M) s

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

& R p9 o6 k5 M8 c" V& {% ?5 \

: W# b5 ?& p6 X

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

+ N' v$ Z- u' j0 ]/ M& C" c( ?

. J% L/ }% r3 L( N- a, O2 b+ I

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

) P. S' O+ E$ V6 M

/ D4 o% K V3 V; J5 `# B

HDRAWDIB m_hDrawDib; // 视频函数

: [0 M5 l$ W. p m

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

$ n1 i/ _9 o/ F9 M

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

5 O* a3 W* O* B

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

6 D( ^9 ?# \1 X+ M3 j: ?6 ]

% z5 K5 G2 X3 v8 a5 Z0 [+ O( ~3 Q

7 G2 G; R+ Q* ~1 |/ T4 T

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

; `( V9 y8 E9 q6 g& k- p

---- m_hDrawDib= DrawDibOpen();

4 P. K s4 _# [0 }- O2 C! c7 \

5 p# m; W4 y! P" H1 l

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

' t. g+ A) ~" B4 y3 F, ?" J" D

7 R+ O" y+ P) h1 t, @# q

if( m_hDrawDib != NULL)

, [" v! \3 j2 b+ K/ \2 H& \4 M

{

+ _( Z. a2 O5 H

DrawDibClose( m_hDrawDib);

; w q8 I/ m' L: _7 ~

m_hDrawDib = NULL;

" e. ^6 ?" h# V v0 b1 k

}

( t7 y: r, N+ j. M& w2 o

" w' l# r1 P% H* r

9 B5 [) [! L2 W: F |0 K

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

8 t$ z( V6 z! I4 u( b1 N. M

voidCViewBitmap::OnPaint()

$ c' r6 i+ `+ d% K( Q3 y m7 a [% A V

{

b: I& @* z3 w! }) S5 s) `

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

' H7 {. E+ ^' [# f

GraphicDraw( );

9 t8 K, ?4 J p" u: W1 j8 z

}

. o, b/ d( }/ K: r: `

& k! H/ Q1 W) H! `. M

voidCViewBitmap::GraphicDraw( void )

2 n3 t' ]6 l/ Q4 ]! Y

{

4 R( H* t' |; s

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

) K4 F. _! T2 [ L, S

BITMAPFILEHEADER *pBitmapFileHeader;

" \8 ]5 ]- G) E* b

ULONG bfoffBits= 0;

8 X9 c+ @& {: v: D

CPoint Wid;

4 ~( U u6 j+ ~9 r

$ B1 i6 g$ ?4 {8 n3 A# b

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

6 k/ ]. Y7 {# N' z; A- z2 ?7 z

if( mBitmapFileType < ID_BITMAP_BMP ) return;

5 ?- N7 q# ]+ ?1 R! }

/ }# \* J8 k( @# U5 `" p: V3 r6 {

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

" _, T2 r% H' S) }% g" s

// 准备显示真彩位图

+ V/ ]& q' Z2 \' e2 F; m9 l

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

- b) e" U& R, Q8 N" F) ^1 X

bfoffBits= pBitmapFileHeader->bfOffBits;

' G) l7 b$ R* @+ i5 I

9 M0 e1 h a2 ^" e

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

1 B4 S) o4 L9 m* y, h( \! V

- b9 n% ~6 w( F% x

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

$ `! O3 n& r! o( u9 c

{

' w, N- J( D5 P

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

) k s" G' p2 s* L

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

# f& I! f- d; p( [: q

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

* \7 l; W8 c7 `) V. g8 A' F" s% V

// 建立位图

N: V5 o% i' u$ h& l2 k" K: V

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

/ k8 K- x3 }9 S5 E& h2 F+ J

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

. ~) ]: t1 Z# D# \0 Z3 t& V

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

! E4 M9 W# s# [+ V. l; l

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

# q2 v! x, ]: P+ c& x4 H( s

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

# o+ ?, L3 `6 |. { y4 ^' g

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

1 n5 ^6 F* ]- p3 X7 W& A2 Z

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

4 l+ {+ \8 |0 s* P0 q; @

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

5 D2 @( _+ a! w, W* r

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

& A- K4 q5 u5 D* A$ E

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

" J6 b) B' Q! x2 s5 o

- o3 g- Z1 N% F

if( mFullViewTog == 0)

, _8 m+ R# H$ ?3 u& ~( j& @$ _

{

& Q4 I1 |. o) X& c# q! \9 Z, d6 P

// 显示真彩位图

+ i1 i4 L, l; t

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

9 G: f' ~$ `1 K

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

4 N8 k* N+ h3 o5 w+ h# V8 W

} else {

7 M+ Z4 Z0 E2 t0 f h; c$ m7 g

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

3 C1 S8 M& I/ B: j

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

! Y; y$ m! O' V0 I: o

>biHeight, SRCCOPY);

) b4 A7 [& l- h" P, G9 z+ o2 r

}

' _; a: m0 Z4 x

// 结束显示真彩位图

' D; c* j2 z& e9 H% W9 \

:eleteObject(SelectObject(hMemDC,hBitmapOld));

+ h4 | v2 P$ b! p4 h! ]+ t! v

// 删 除 位 图

7 n l7 L7 a& B% |* z/ x

} else {

5 i" o& e3 |/ P+ }

! D9 N3 D( R% h. F/ S6 p

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

( y. J+ H: Q0 L8 k

- K" N# I, l( L9 |; u+ ]7 k# h

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

i- a* a; ^" ?) }! C

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

/ s( b X# R+ e" q

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

' H. s% j3 |4 v+ s

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

' l) I' ~2 I" G$ _

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

$ s$ h% [( R l. H. M: G; z% a

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

+ U( k6 k/ M% v; X. F& E

9 `4 F8 l+ |: r5 @ v' y

// 显示真彩位图

2 K6 U' `4 Z3 _( l) A

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

; K: o( J, V6 e+ S5 o; r

0 |2 G3 C7 _* G, c" G

if( mFullViewTog == 0)

- h! ^( U/ D& G. Z! g I2 E) W

{

0 n3 _3 Z: `2 y2 L+ O

Wid.x= mDispR.Width();

$ V1 V9 @6 T! f

Wid.y= mDispR.Height();

$ A, P+ r/ Y9 G' Z1 B

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

6 J( a* n: n. K

if( Wid.x > mpBitmapInfo- >biWidth )

& `3 d( I/ c% C( f9 \

Wid.x = mpBitmapInfo- >biWidth;

7 ?6 I S: J2 m7 j8 P

if( Wid.y > mpBitmapInfo- >biHeight)

6 [( _8 |" v4 k8 @* h

Wid.y = mpBitmapInfo- >biHeight;

: |* C% I; r2 i- f

( _& z" y6 Y; x

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

0 T) i( X* D- m9 }3 d3 I

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

! y6 {' I7 W2 K5 g

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

0 n7 B& X! b# G5 R( V

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

5 Q0 }1 n- P* p. X

} else {

8 s# q9 l" Z9 Q$ Z

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

* C: ~1 w) }6 d* O: \6 E2 o

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

# ^7 ]5 r$ F& I8 S0 l1 J$ @2 m/ X1 f

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

1 Z9 c; E5 X3 |4 x' W8 G* `( i3 ^9 M

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

- V; m9 T6 p+ [7 S3 R1 A5 ~

DDF_BACKGROUNDPAL);

! _! D5 ^; E! @, M

}

( j6 ]3 j8 e( ~" p8 F

}

0 q6 ^) I- U; V; y" r5 B& L

return;

: m9 A1 h& b& K {1 B

}

/ ~8 U. ^, \0 N

" ^- v; K7 u7 A9 j g, m4 a

1 b! `) c% o. h" d9 m! x

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

& Z2 k& k' w/ }5 i; w) Q

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

R( `) C% q+ g. [

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

+ m7 J+ E- O% F' j- ^) p; a

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

" E$ R% A- Y5 `7 b

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

q0 q2 P7 Y; f6 N* @- \: ^

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

1 E5 [ h. Q4 @2 u

- b0 s6 k, G/ ~, W8 d0 n

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

6 V0 q9 K: V5 Q1 L3 m% N$ F( h! d

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

( f+ n7 h& C- K- H- T7 b4 b

. u0 {) T* y" w

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

# V6 N" {$ F6 t! X

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

6 [0 d* P, \ w2 L1 H9 J8 [

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

# O/ O0 @- S! ]1 m7 K

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

# Y8 [& C- f8 k I4 J; [& R

。代码如下:

% p( n, g1 u3 ]( Z

' m" e- G+ Y+ [9 [9 S7 ]

void CMainFrame::OnViewBitmap()

7 w, @1 A5 S. v% A! c+ N

{

( n6 b) {) c% T/ f" O1 K. l x

// TOD Add your command handler code here

3 q! C& ? x* [. T9 ^

CViewBitmap *pViewBitmap= NULL;

1 m# b/ C3 z. O2 N! {2 x0 p5 @, I7 B

! s2 U% \* L7 h$ h

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

- u- h" T u/ K

pViewBitmap- >ShowWindow( TRUE);

- k7 s& J$ C1 D! f2 _

}

6 _( ~7 E" k/ R/ V @4 Q

% W" [0 c) H6 @. w& u1 N

1 M0 w3 o( P6 e1 b

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

, ^( C" J% s6 w9 A/ T! R0 F9 {

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

, j' c' w" G0 v

3 Z+ L% j' z8 v4 E

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

- f( O @7 ?4 m- W5 j

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

& R& U" S# D# X

: i2 C) p1 ~* G/ }

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

6 z( t% @8 l: Q- X) G

8 K7 Z; L9 f' W' @$ j' J. E/ Y5 A+ L' ?

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

1 L, U3 [7 x( P3 B/ L2 d

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

1 _9 n+ m8 P: y# H6 W

) @) |- H) E! {

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

1 p4 f! L. Z' A. o7 `( V" Y

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

! e4 v8 }* p* u# k1 k+ ^

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

: i% O+ E2 R1 Y5 M2 C+ b

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

h6 `) w$ n/ r. c% i" ]. n$ W

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

( U5 P7 r1 O( m8 I2 P0 f Q8 w# g

$ h: v) E6 g; e0 C6 b* e

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

- @. m$ Y# R" ?

就可以显示该位图。

! f' g, K5 o# m+ d2 |+ q( w

" B, H+ ~8 o% o3 H5 L; z# ]& V

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

6 x& ~& h. Z, s, V4 \! z5 [) ?" L1 D8 ~, F( s ?

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

; C# G ~0 u5 F. J' u% U/ D/ }

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

+ w8 P7 |8 V, T) k; P) N( f: V

真小,显示速度快。

% @1 R5 e Q" V

7 r5 f. d1 u/ a+ I

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

& Q, B8 @0 ]% @. B

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

8 d* b0 V6 \0 y( ^( {/ x( w

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

; s1 L) d) \7 v

- [8 d- \ D- Y$ J; q8 x

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

& a6 Q! h8 c9 l1 o* ^+ }* z0 }

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

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-18 17:31 , Processed in 0.522335 second(s), 52 queries .

回顶部