QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

) P: Y) b6 N7 c5 n5 J7 b. V3 `

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

8 r, A# A' u! O2 ^- `9 S, g( Q4 w& u

张义云

# T4 E7 G0 P2 n2 p5 u# I! \5 A

4 Y. Q5 o& N1 M* ~0 u& W( l

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

/ K r" A; }& W, B, r

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

. A' j4 t6 m4 B+ Z1 c" N

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

+ u, j$ t+ n( D- ]6 r

. a3 p9 f% F1 ^' `6 R

---- 一、BMP文件结构

' ~6 ~" _0 I+ L0 }& c

T9 Q" O0 ~$ I5 Y) v% O+ C4 A

---- 1. BMP文件组成

0 s- ?" @* B& ?& P5 j

/ l7 W% R3 w4 g! p) v

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

3 i0 A9 \# L( M( d

8 l; x! x% Z8 \5 U- Y: b

---- 2. BMP文件头

$ ]/ T s. S3 Z8 t' N U( j4 }, b

$ j' P' L- V* ^( K. V3 N9 o

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

/ M7 n/ r( \+ \

8 p' d A+ k( D: u. f( J# O- O

4 B2 t( X3 U3 R8 h: F

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

! f4 j9 C* c/ J% Y4 e9 E' T

% |# T; _4 C L+ c5 P- n

typedef struct tagBITMAPFILEHEADER

" |, I7 T1 d( k- K9 k- W% } _4 n

{

8 v2 u: u& Z5 ?3 L9 W! H) |

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

8 F6 Y; X9 s* [6 r8 H& l

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

' U+ K: A4 w" ?- m/ H& f

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

9 g; u: ?5 R* H7 B

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

, G$ ~# P+ m" [% x7 }8 K9 y* N

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

3 X5 z) p) d6 E0 I

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

$ f6 s9 |$ S$ v+ \! G2 q

} BITMAPFILEHEADER;

& j/ s3 x# U& _5 j

0 D+ Q7 a; T1 @) i" D

2 B; ]4 V1 ]+ K. c$ a

---- 3. 位图信息头

' p. O1 ^) I( W5 M" ~1 f. ~7 r2 ~

----

" U+ g/ E; Q) X/ H+ u

^' O( C( E1 Q3 G% q$ S, T! d

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

* c' s4 Z& u7 w

typedef struct tagBITMAPINFOHEADER{

3 B& v6 \0 x; Q

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

2 ?/ O+ z0 H" v- C$ ]0 C

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

8 N9 y( k3 u" b) b! L1 a# ?

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

' s: N6 s. `! w6 w2 `

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

* j! c Z" f8 g% G

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

5 P. D B: ^4 P; O/ {# G1 |! {# S

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

/ s* A) l2 S$ F/ R9 O; p

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

2 j: K6 y8 V) T9 t) O

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

8 b" g2 |. W% l) Z4 ~. B

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

3 F) N. j% t8 l

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

- F, y' Y& h2 A: b: U0 j

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

# K& |5 z% W7 h9 q; u- f

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

- u* l. o4 g3 {* r/ k# v) |

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

5 [- a0 }3 {' F0 ~% G5 R$ M7 \6 H

} BITMAPINFOHEADER;

$ h8 ]+ O! g" I! ?% Y/ }

, ~1 q+ \' B$ s' K" g+ p3 J

' D$ D4 J- ^, V. V

---- 4. 颜色表

* j: j; _. d- L& R. g

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

" E3 t; P4 Y! k9 _

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

( s% u% g% i' q$ c

4 u8 b' c& x4 F8 }+ s

typedef struct tagRGBQUAD {

# @3 o" S$ d! q: n2 j

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

5 q( p6 h+ ]4 B$ S* A# l: M. x, ~

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

7 m. p% ?7 Z" `+ o, K

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

: j! r9 V5 Z" p5 b3 Z! F

BYTErgbReserved;// 保留,必须为0

/ w+ r) k+ m2 ?! E) f, r4 O

} RGBQUAD;

3 B3 m' g: J, Z, z; d- @

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

: b! V/ Y* K1 i4 g m

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

) ^# l5 _# ~ o7 f1 V6 F

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

7 v) S2 b" _9 ^' Y0 V

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

, j, I9 S: g p c8 {

typedef struct tagBITMAPINFO {

. y! G2 H# U. F

BITMAPINFOHEADER bmiHeader; // 位图信息头

7 k3 p& T3 x; r b: P- N! Z* }+ ]

RGBQUAD bmiColors[1]; // 颜色表

, x. n% x, n9 r! g1 X7 f3 [

} BITMAPINFO;

4 ~; C6 n/ M9 ~9 J* a% a. M; Y

* ~$ I! r0 h- T

8 L2 {, r: }0 U( M) _/ e) T

8 T) \" C5 X! h

---- 5. 位图数据

4 ?8 L% W; V" M$ E

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

8 H6 C8 S7 O# V

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

U: w0 r9 V L4 X6 k9 z/ Q7 ~

# R: N- d0 w; [/ H

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

8 }' N+ y+ @. i" Z+ _1 E6 J* z

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

- O) y) K; r8 ~9 E

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

3 F% ^: j( F `# q

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

8 g7 ~* l7 d/ F) ]; H" k

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

, J! U, S* D+ _; l, M9 ~

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

9 ` {3 o" ^7 P2 @" p# d4 x H

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

! x: }, L2 y! S0 j) [

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

, ?. l% [6 b) u! [

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

2 w; A( C3 ?. r6 H5 j, q/ N

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

0 q# k4 {2 q0 C# P

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

2 J: u: ]: `& M

DataSize= DataSizePerLine* biHeight;

( ]- ~! o; H! B- l/ J& W

& h4 _) f$ D+ o: U) \1 B+ E

5 Q) U0 Z m0 i& R; @) R- R' W

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

: l- L; G9 R+ X: F) p6 g9 d3 m( i

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

: M/ d" E- t4 `* q U j' v' Q3 J

& U) R- N9 k/ _% y- B* |

---- GlobalAlloc(GHND,FileLength);

' A1 N6 ?4 B7 @) ~( d

( C3 G! J9 l0 |( c3 K

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

' C5 g7 w/ c; i, u/ s

% J0 T! _" y: M, y! B

---- LoadFileToMemory( mpBitsSrc,mFileName);

# i6 l- Z1 O2 Y+ j3 H9 v; ]* B

$ \1 M/ d1 [: I& D9 ]$ X2 r& o! U( E$ j

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

. W! q+ _4 I7 h& V. U

- B7 }* Q x+ Y7 U! o, u

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

# _( l) }0 L. `5 h

DC,

9 Y& \0 |% t, |: j/ ?# K1 u

) T- j4 j1 ]- d0 }

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

! T8 H( M0 A8 G* @2 h

+ K: H; C( ^ E& u5 z m

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

+ W3 J& j! T/ @* c

R/ ]" {5 s' Q8 u: z# t

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

4 s* l, P' z9 k' S0 g6 p

0 G8 O- k% i/ T% J3 g) L

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

6 x4 Y5 r4 j, e+ V! d

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

$ y7 ?$ t) o, f- ~* w" q

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

" K/ ^/ `$ w8 ^' v9 K0 k" x

( [* `" e3 b3 t3 `6 r% b

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

" q0 c: Y, a8 [ m! o

; p- d6 i6 c/ F' z3 p, i9 I1 G

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

" g! c/ f4 B( Y1 t, P

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

! g+ N2 N! M' Q |: r

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

7 c9 j% w' F! K

X, o0 i n1 Q2 t- W

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

: h* U: L; n1 U' C) M) i6 j6 R

! V1 G! z5 [& x' ]

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

, M, k- V8 u" j, ~" s* ~$ ?

R( f: B0 Y$ Q( U( P4 b

---- GlobalAlloc(GHND,FileLength);

0 x, ^3 @. R7 q W% q5 N

) l* X# h5 S) E

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

* X4 v. s- E& D- q, w

% w/ H2 G9 Q! P3 q) S$ ?+ o

---- LoadFileToMemory( mpBitsSrc,mFileName);

5 o; a- \: n# q& v

. F+ X# k, w; d3 w

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

# }, g+ C: {3 `. Z. I

& q: I" h, O; ~; J

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

L! ]* y* c* v7 @

% U2 p, g7 A7 e" t

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

3 l3 a0 n l" e6 I; ^6 a

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

* B; x; _' k2 T

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

' o+ P" l' {" m

- Q7 R) n; L3 K( a, M& G

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

* O: s0 r/ M" D* L z7 Y8 D

' P) h1 ]& k( |% @' E; u: k

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

( X) z% V, k0 `% H) D

4 {1 N: P/ d5 N* J" s

HDRAWDIB m_hDrawDib; // 视频函数

- X0 H3 w5 D b' k/ W

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

, r$ g- s) `/ M' p% a2 ]

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

/ j. e6 g4 U( M

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

( W2 P% N% S& U& U8 R7 G8 }

$ n& Q" m$ w# X/ c4 s- v/ i

Y# O0 \" ?9 E( N" _ k6 |, r( ~

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

: r& K9 z8 d* u8 X6 H

---- m_hDrawDib= DrawDibOpen();

5 Q% x. \. ?% q2 }0 K

3 {0 Q6 P1 H3 c# G" A2 H

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

8 \0 A ~! Y9 f; v$ B- I9 f8 A

1 g, B& C4 Y1 H/ t8 @0 R5 Y! p

if( m_hDrawDib != NULL)

/ t5 Y) B+ P/ }6 ]& E

{

" t+ c1 k6 i* d$ |

DrawDibClose( m_hDrawDib);

' C! d( I9 w( f7 E

m_hDrawDib = NULL;

' l" R7 h! w5 s7 E h3 b6 i1 ~, _

}

! G( n/ ^3 T B# c" d

2 ]% s' H- {6 r) b' p4 {& C7 M0 _

1 g# z P4 e- Z8 q, y

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

$ n& y4 y. h* }

voidCViewBitmap::OnPaint()

- m8 o0 ` g R2 I6 b4 o( [

{

7 d, v! X q! T9 d p- B. g$ Q& E4 t

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

& T& H f! \( O( V

GraphicDraw( );

* R0 w% G0 s8 L' }% e# c

}

( I5 S& A' e$ b5 v

E) {8 x x/ F& ~$ v

voidCViewBitmap::GraphicDraw( void )

1 i8 p9 u5 h) Q4 k" W( I# X$ v

{

6 D6 h5 H$ ^' ?) }- m

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

& f. e" X4 {3 @( w g8 q- J

BITMAPFILEHEADER *pBitmapFileHeader;

% O" h/ u6 J% H4 \- ~+ g$ y

ULONG bfoffBits= 0;

* M9 K$ q$ F1 ]0 }6 R

CPoint Wid;

. t$ U6 i/ v2 }8 s9 P$ l

; J$ R$ _. I( @. }

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

% n. C" Z; \( c' ~

if( mBitmapFileType < ID_BITMAP_BMP ) return;

: m) L) u& ` J3 y2 ?

4 Y5 E( s! m4 c, ]: ?. m2 K

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

9 d7 c9 a3 `+ ^- ^, ]3 H0 Q5 Q

// 准备显示真彩位图

. R9 ~" E7 M: v1 i: ~4 h6 I q

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

% C4 X: ^/ J; C- t

bfoffBits= pBitmapFileHeader->bfOffBits;

$ _( A! f, _# D- e7 @! r) Z- G

1 K6 z" l: D: P9 G' R3 p

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

/ D' h& E% G. q1 G1 G5 d

0 Z3 v9 r1 ~4 _+ \

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

" E' p- d8 c+ T) f, Q; v

{

1 W' ]3 x: ^+ ?

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

( H2 }: G1 K2 a

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

+ n& G0 L+ ?, A) |/ L) X. M; x

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

) H8 P, M' z( r9 L+ \

// 建立位图

$ u5 N- R) D- @7 j0 j

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

& A5 {5 r. A. }1 u4 Z5 W* C; O7 n7 s

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

& b+ N0 u" m* Z0 b4 b# j

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

0 g1 O( {% }- j" N

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

) Z1 A3 K2 b, I. [, D+ H

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

; l* T9 w' w$ O% ?! F4 P3 q) e

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

8 {/ o+ m/ y# @; T5 }: J( H* T

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

+ N1 Q) v" K6 @3 O. U

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

/ H; k5 V& m2 `! x/ ]

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

9 e3 v" Q2 o8 f: Y% y

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

* l1 {& u* I; l3 w

% b( ?) @9 U: ^" z

if( mFullViewTog == 0)

2 M6 g6 T( |& }0 ^" u3 Q0 O

{

! C8 W/ t$ t) {8 ^# ~# q

// 显示真彩位图

# F" M: N/ v+ G# G3 a

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

+ s+ d) T, [/ R2 g1 a1 y3 [5 y$ B& b0 r

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

6 f* M2 e! ~* @( n9 y% g: z

} else {

$ O7 c- B# N& D4 P

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

+ v/ R* Y2 `0 Y8 i

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

: x9 z2 B$ `6 x* W. L. R

>biHeight, SRCCOPY);

! |4 d; L0 j% }* B/ N

}

+ V6 p: @$ _- \! H. \

// 结束显示真彩位图

6 t* j6 `: ~" V/ D! j/ [

:eleteObject(SelectObject(hMemDC,hBitmapOld));

8 c( C1 `6 s- z2 \5 ?9 E; P! g

// 删 除 位 图

1 k/ J9 K$ b: q- |% T# R2 l# z

} else {

- I% a7 U" d; }4 k

+ b* t' T0 q2 A( T2 k" V8 |

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

; l7 `( f, D& f* ?5 a3 ^- \

1 C; i8 f" P: Q s, J, ? r# f/ a) ~" H

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

3 E) u6 A# \0 t5 f% ~

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

2 b# k& O0 V: N! i" q0 i

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

( d6 q7 m- s+ c. F' P# \

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

, l: w- m! |7 z8 C

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

# h4 D% a+ }' e, K) X5 E" V% M

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

2 `9 P& E* n- @2 h

; }1 W0 M/ \: c* W

// 显示真彩位图

6 G- r9 K# `8 I1 x* H; ~0 m

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

) E& G9 L$ Z4 b d& X& e% v* K

. c; Q" {4 }4 k+ T

if( mFullViewTog == 0)

& r/ E: G3 P6 n! _- f5 @

{

8 a! m2 M% }6 i1 n1 p! [( _

Wid.x= mDispR.Width();

0 Q* C; v5 v- S/ o% o4 q

Wid.y= mDispR.Height();

% \- T7 m; I3 f+ {! V+ I$ I

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

5 k4 f' r9 `; `* j% ?+ |

if( Wid.x > mpBitmapInfo- >biWidth )

; O) E$ D! [ p. P

Wid.x = mpBitmapInfo- >biWidth;

0 a# L: t- B i$ N! q8 ^

if( Wid.y > mpBitmapInfo- >biHeight)

+ d; h' p: H ^. I- o

Wid.y = mpBitmapInfo- >biHeight;

) A$ b( t" R) v* T0 R

" g$ J* c/ h. P

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

3 X# V7 a! ^4 J

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

# Y3 _% a( P, g5 v0 R# Z" E% Z

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

: m1 _* G) `+ C1 B

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

1 e2 p5 o% `) }9 N% `

} else {

$ z n6 k" K& u1 c- l

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

6 d/ h4 C- u% y* u

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

7 i, b; G t- {5 f* Y; p/ }

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

/ t7 u3 u4 u; y( n2 e; I

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

6 p) R9 @; |& }; X! ]

DDF_BACKGROUNDPAL);

# J; H2 D7 U' K4 M# z* n% u

}

# Y3 i h" s s: X/ j$ Z; R

}

0 |2 |+ [( p4 t& i4 }/ U

return;

6 }( [. U) z1 ^8 O& m/ t$ r- ~4 }

}

/ B* Q& X1 R1 L. u& E

: a7 z7 z7 L2 ]. A: n/ z# a

7 _3 r1 @+ A) R/ c3 R7 w4 L

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

$ f) s' J6 s, X4 P0 m" i( G' m

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

* g% w |% V+ k! b. e

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

. j3 B6 D, n5 x0 d! X/ J( ^

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

; k% r# g5 ]: ]# d$ S

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

% n' F$ k G; P0 o( d$ J% O' _

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

" [. e. V I7 i6 X9 d

/ u( N1 e D/ D0 Q. ?( y3 s7 F

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

$ ]0 p z, C1 H y

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

( I4 [( H* ~5 P; ?, |1 v

3 [# f/ U. s( v+ |* x" X

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

7 c( G' ?& k- d" K0 y

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

* g4 U8 W6 w/ ^) o1 F9 Y# e3 b

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

6 g5 W+ D# ^) x+ `) x

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

4 f& m5 z1 Y4 d7 f8 E

。代码如下:

* H9 v2 w: \2 h2 U2 b# f" b8 ?

& I$ d* t& S% {" ^4 `' F; i

void CMainFrame::OnViewBitmap()

" Q. I/ h7 j: Z& L. C7 X

{

: w% K! } W3 n) T7 L) Q7 M5 `/ ^

// TOD Add your command handler code here

+ G9 q% i+ M- e+ H6 N

CViewBitmap *pViewBitmap= NULL;

9 {% G3 X! ~8 ?; L. R& z: _

! B9 m& P8 L2 f+ b2 N7 C

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

5 n; }; j& r$ l R; s' t. P: r

pViewBitmap- >ShowWindow( TRUE);

% q# m d! b$ b1 y4 J* F0 s

}

0 K/ s" i2 _* R6 d3 z3 m1 j- I

# h" J0 N# C+ A& I& J

! ^0 W6 z( o% t9 a o

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

?: X4 ?& q& ]4 H0 p5 y- x! @

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

6 Y8 D/ ?2 d) _/ m- g

6 P& O. E( z+ W

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

2 O& c. J2 m5 `$ _% N4 d

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

5 ]& ?& C" ]/ B, s% V2 f3 k5 ~' G

' f1 ~8 C. X: ?0 D

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

$ A4 \5 ?$ C+ i- ]7 j

0 k0 t3 N/ D8 @, y, A" \8 y9 p2 U

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

* h8 }! ]: i H9 Q) Y

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

W* U8 Q t8 y: o# o

8 S4 T9 v1 Y+ ?7 J& S

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

. |& B* { F( w. f3 o0 k5 I

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

; s9 R+ i! l8 }

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

: G) V4 ~; h! _' A8 U

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

: v+ f& F- @# H

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

) |/ I4 R {# Y% F8 G

: U0 k7 Y8 v1 V+ m- b& X

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

- n- s" y# K, d8 }6 |

就可以显示该位图。

! @0 J' E( s; r% k& i: o( `

+ L0 G# f$ j" z+ n8 x

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

' C& ]! ^& |; }' d+ E1 o . F: F! b) ~3 A% p

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

* e& c0 U; `) N5 K' r, I

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

2 Q& I3 O( G8 y( t4 h: S% I

真小,显示速度快。

" I8 `9 ?) b) }0 W$ N, W) b' P

2 v3 P9 _+ S, }/ D. e( t

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

: [* Z6 z$ t& [- I6 M

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

0 @, E% F1 ]3 r' i

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

5 V. f7 ~7 B2 ?4 a

1 N0 l! ^1 p1 ~" s& p

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

9 R/ d5 E. A/ {2 b3 ~$ 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-6-12 19:19 , Processed in 0.414181 second(s), 51 queries .

回顶部