QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

5 E D$ p! T6 M5 _, T2 W- d

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

, U' q) l1 Q" Q" z |1 q% D

张义云

8 {8 o+ p1 n S3 n, v5 |

3 I. N+ o- t* ^- J. U2 V; A% t+ B% @

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

0 Q2 T, e; v0 O q

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

$ X' r7 |) Q6 H$ }" M$ d

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

' @3 o2 r Y: {3 {9 |7 j0 }

3 H+ C% [! i# `/ H

---- 一、BMP文件结构

! u' \3 @3 L: H2 f4 E4 J* Q

( J D: P* |, v8 s' k" g0 ]

---- 1. BMP文件组成

8 b9 h7 d9 a* C6 E: d

$ X0 ~9 K$ q+ q. J( _; q

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

$ o& u6 ]% m- k0 P3 a+ g) Z+ j0 D

) r+ T- F' O$ p4 _

---- 2. BMP文件头

4 A. q/ s. |3 P/ l; z

, M6 V V! F% E* R9 l- ~# w2 P* P

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

* f* `4 @ f4 `* m9 P' ^

g8 k$ u3 K: A" ^7 l

5 ~0 T6 ^& w7 ^

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

( i' g# l# F j

. Q% K/ K7 W' c$ B1 P# p

typedef struct tagBITMAPFILEHEADER

7 E% x* e! g. p: Y- D0 r5 _: ^. ^

{

4 q: O' D) N5 B! G0 F/ D

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

( _) K& U) N2 M/ F' ?

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

) ~ T' K; e) x( G8 q) u: G% R% ^

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

}" Z+ t4 G2 `+ ]. N4 N

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

9 r4 q3 h8 K% @) ?

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

4 H2 n: @ T. g) K' V! m

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

P9 S: i; p J; E6 e& g! \

} BITMAPFILEHEADER;

0 l( D: t3 g- i$ k% I

0 o$ j9 L/ L* E( V4 [9 }# Q

$ [9 Z1 p" B4 n0 b: v+ _

---- 3. 位图信息头

& _- ]7 q- u) G" {+ p

----

- _2 w0 d+ t# T Z2 G

1 v# J& F0 ]- r# J# H$ d2 j; P

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

* O# C7 w3 o' _/ U- h

typedef struct tagBITMAPINFOHEADER{

. k+ T; V. J- W B X

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

; c" p; f( D4 k7 x

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

5 s* k% p5 _$ D7 Z# E2 G

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

k+ _5 [7 }$ Z9 u4 p7 \4 i9 m

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

8 y) ?. Q2 M; x4 m7 u7 ]) l: z3 K

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

, y" Q( j* @9 x" y% Q

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

* s p* ?) t3 B, q

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

. Z* t x( @# X7 `' a: e

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

$ v+ M' c( K u

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

7 o7 G* m% M3 z# l9 O

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

' Y& T Z3 q3 x: o. e" _; N

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

( H r. P4 |5 O+ t0 H( Q

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

# X9 a4 H: J" I! W

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

! D$ J% n) F6 G- ]

} BITMAPINFOHEADER;

$ Y n1 ^; x9 I& z( p/ M

% p+ b( D& v7 T/ W; l+ M; s" N, c

5 S, r4 g, ]) M R+ N" k

---- 4. 颜色表

' m' C& B' Q/ p$ J' _

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

8 O4 a' i- S4 p

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

' Z+ `: Q3 n5 o) _6 l' ^

+ Q% \3 K8 G/ _! M

typedef struct tagRGBQUAD {

7 l% D2 E+ k/ _9 j/ C0 ? k+ H7 P

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

. y( Q6 M" J- ?

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

2 m) z& H& Y6 g9 c- t

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

8 g! T8 E3 R H' G& i

BYTErgbReserved;// 保留,必须为0

) a" q3 U* B# p, a0 N7 n

} RGBQUAD;

2 R* Y/ ?; D6 V

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

0 S/ |1 V/ O# s7 g& c, @

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

: }. n( P1 {. k8 m

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

1 q* k% a( O* N- L+ J

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

* x2 M+ A C8 Q J T L# Z& D

typedef struct tagBITMAPINFO {

. y1 |+ e! Y3 T( I9 v f

BITMAPINFOHEADER bmiHeader; // 位图信息头

8 t! \/ |. ~$ V, `3 l- u

RGBQUAD bmiColors[1]; // 颜色表

$ R' O3 e/ }0 M3 u" H. m s

} BITMAPINFO;

) e# B6 m( x7 y V

. G$ I. I7 W3 v' f; q( Z u

6 a& K$ ] m; T$ p- v5 g6 y

) w8 Q4 A' \$ q" ?* I4 s8 Y6 n

---- 5. 位图数据

* F( o% V8 ^& @% k3 R9 _" d7 ?

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

- Z& I& _2 b2 @/ O8 y7 a6 X

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

* _# q, f$ _; [5 D+ A

9 |" A6 h7 \0 O5 O9 \. e B

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

9 C) P8 Z' P3 J I7 B2 h3 Q: S' [: e

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

8 `7 S8 S( {4 w2 |+ f! O

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

; e; L/ X+ m7 V

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

" w+ @4 u. h# `2 A- _

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

* l) ]0 @* Z2 J' `6 y* k5 o

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

2 |1 {$ v9 @& R S* e/ s

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

. {+ P) l' m5 V2 K- E0 i

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

, f1 C% D6 w# q0 }: {

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

" B0 k% ]0 W. _. V5 {1 n

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

; }) A# {" A- [! o

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

5 J, [: ~1 o+ v4 ~3 ?% b+ f

DataSize= DataSizePerLine* biHeight;

& K# [5 i! S$ U9 g) {; D

$ e# T. J a) e- j2 z8 O

+ G% c) C! M9 z* _- h

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

$ ^! ?- R v }/ V4 L

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

7 U! D' Y- ~# a1 p! J. Z

, Z7 @% F9 x# Y }

---- GlobalAlloc(GHND,FileLength);

9 k1 K$ I* A: U9 g* ^& Z

" u( @+ C* l* Y% Q; C; Y* ^

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

/ Y+ u0 C8 ?6 i x; {

& Z$ F& w3 u- b" F% N

---- LoadFileToMemory( mpBitsSrc,mFileName);

1 C( R. E( Y1 U; ]7 o! [" f

- b/ a* D& ^8 [: ?% k3 u! Y, y( A

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

' V- z* m. n, t2 x" Q: L

: b; L. I: D6 @0 d

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

: `% O: d4 q, N I

DC,

* Q Y# Q4 C4 G! z$ V& C

: f) c. {% z" f& L. @

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

9 x2 _( N, b$ ]! c o% m- `

$ l; Z- m; k' x3 M# o% L* H

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

/ \. k- m% y) s1 c

/ E$ R# [ |2 u y! C8 c5 e

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

9 h1 P4 M) ]6 o. I: s8 d$ o

$ t) u# f; L& u) w

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

5 Z2 p5 e7 k. y0 z2 l9 X

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

4 g+ ?% f! F- t8 `7 y6 }

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

" L- g- p$ Q2 |

( \- }+ v( S' a: V2 n v

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

' H) F6 x( _- u) D3 d+ x1 u; W

/ Q9 i) e1 K( A5 |

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

( [6 ^# t+ y# I! |- M& @5 w

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

, b+ M, L* R) O, e& R5 Y1 P1 l

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

* _4 i8 N- V d# P! g6 C) a

, p$ _2 A& r+ H

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

. B4 {( E5 X. M# ?; `: k i

3 H$ A7 D3 n' O

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

/ a% Y* l; X0 Q! U0 W8 ~! ?' I( U! [

/ f, y' h# U) R* F! V2 ~

---- GlobalAlloc(GHND,FileLength);

7 L' H: A) c$ R) _& n, Z2 m; X

3 w. }' }/ u/ u! S- w l \0 t; u/ f

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

) M- s& F+ {5 H6 |1 e

4 h3 ~/ J8 b: G# `( K8 z6 ~

---- LoadFileToMemory( mpBitsSrc,mFileName);

# o; [ F/ M8 z) G4 F1 S, r+ Z# M

* [* s9 |, v) `+ V

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

5 M, z2 S7 f" p

$ A$ H: c. v. l; [8 m; g

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

5 m& \1 |* }" d, L( G

. S+ n* a A. N& S% [# }

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

7 ~4 V! s' K/ V g# g6 [' W

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

- ^( r( @- F% Y2 l3 b' T

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

; I8 q# ` B0 A5 q

! N! l; J6 c5 E2 m/ ]

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

9 @9 ?+ n. `) n& b2 v7 @

" f4 b' m X* j0 H; M! D/ P

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

1 k6 s$ t. L w. j0 u3 Q6 S5 w5 W2 A

# {5 r0 U+ A( }+ v+ P4 a1 S% p

HDRAWDIB m_hDrawDib; // 视频函数

4 i5 \ J+ ]( [# X

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

3 Y2 y, @* J8 `* X: Z& Y' j

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

8 f) S) b# c: W8 A* r8 Z

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

# _" K% m: D; y _: M' U9 u1 E

* M) H% q5 f5 L% y% y

" x/ t' j' y7 m( E7 E

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

, O' U i$ f1 k5 f7 g p

---- m_hDrawDib= DrawDibOpen();

2 g' Z5 Q/ C& i h* l

: b& Q, B! F& i& r) @+ J/ T

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

9 G/ u. Z6 c( F$ O; w

2 C( I2 Q. m F# u

if( m_hDrawDib != NULL)

$ \+ l$ q& [: M+ Q5 ~/ `: R. S

{

5 R0 H$ y0 ?& X5 U% m* W$ p( p

DrawDibClose( m_hDrawDib);

) L: `. ?/ S5 H* t

m_hDrawDib = NULL;

+ M) G# u0 j5 m

}

" c, ?$ Z; m4 E9 J, g& T* Q) {

/ d$ y$ j2 C2 \" W

- J1 c! l# ^- l2 J0 t. x; T

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

4 D( O+ E- w' D

voidCViewBitmap::OnPaint()

! ]- ` A( K! f) l

{

! t+ U7 \* d5 ?# c/ x

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

6 z' h" q5 ]# n: ]

GraphicDraw( );

! i$ _ k2 l2 |3 \9 S& m

}

: b: y- m. X* ^. G, \

; i5 N R! M, c K& h* ]; _# C( f7 ?

voidCViewBitmap::GraphicDraw( void )

) P. n! n5 d. k" c! a: e' O- A

{

& H m9 C; S2 _* @5 N) ?

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

% q0 t/ A5 n) F# O- A- a

BITMAPFILEHEADER *pBitmapFileHeader;

% v# W6 Z2 k7 K' Y

ULONG bfoffBits= 0;

$ ]1 f* \8 `# m) W7 L* [

CPoint Wid;

4 \1 J: @ q! h) j1 `8 V1 {* X

% C" |" V8 \7 K

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

- M, q# k& g$ `5 Q) v

if( mBitmapFileType < ID_BITMAP_BMP ) return;

+ \/ a: E% I; c& ]% `* H' M. S

+ ]9 H0 [5 r3 ?; ~, R3 R

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

9 G4 o- n, E% g

// 准备显示真彩位图

5 Z1 Z" j: z: {# y& C! f% g, }

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

2 Z7 l: i+ R c+ H0 L2 C

bfoffBits= pBitmapFileHeader->bfOffBits;

, i6 K& ?$ x9 Q

* u# Q3 e" A5 L( H

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

6 P7 g; X) U, M0 A

0 S( `0 s* j$ w, f+ j5 H) D

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

' [! O M, Y0 A5 h7 c' t+ ^ \

{

. ^' ? M2 i4 K) W) N3 h

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

; R: y& t) ]/ z% e( D2 F9 P0 r

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

+ r* i5 A. S# D# }" M5 X

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

; g7 X2 S7 M; V# V

// 建立位图

' }* h8 G' O. o

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

, ?, w. f$ D0 ]- c

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

0 l9 y; Z' z; A6 r5 q u" _

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

. v7 E8 ?, b/ U. S

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

5 X* G3 B1 F* V

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

' H' f" S1 t3 f7 h+ ~" C! y- @/ p

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

/ q2 G" t9 r* g* ?

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

/ V E/ Z/ F/ c& g: a/ B/ n8 `9 |

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

( B( A; s0 w* F& m8 t9 { U0 ~

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

+ e6 H& j* U; w

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

: r% z! n) |6 _* M

$ ]8 g8 O: B2 l/ E( c2 p3 m7 D

if( mFullViewTog == 0)

! \* n j" N4 {$ O X; K: ]

{

' c; g1 [8 X9 S8 V) V$ D: _9 m# g

// 显示真彩位图

) X) r: y* v( j5 `6 }6 s2 l3 p6 ]- t

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

# i# y7 E: Z2 i6 A7 q& A

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

% J$ r* ]5 Y8 T, Q1 H" V

} else {

, B" K" X g7 b" T; ?1 {

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

* T ]( h4 m! S: b

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

* o# F0 n) \# l4 \

>biHeight, SRCCOPY);

" m8 s7 n" Y9 w2 M9 ]& h0 Z/ O

}

9 U% O9 k* q9 N9 ], \ O

// 结束显示真彩位图

# \8 r" _2 ^5 ^

:eleteObject(SelectObject(hMemDC,hBitmapOld));

" @1 m* ~6 F% ]

// 删 除 位 图

7 d6 {& f/ a# J' Q9 l2 X

} else {

* U* G( x5 b7 b

5 u1 G; M& b2 H% w' V

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

% h5 W( J O6 b0 Z

3 E" q% ?. D* Z1 V' W6 k

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

+ x& a+ h8 b( U4 q& s+ I; i; G# Q

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

$ B3 b4 C! U4 I8 Q Q) Q$ u4 Y

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

, s& {' ?( l6 b: ^& O+ f2 d

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

1 x, f' P: Q9 c( `7 M' U2 \- L6 p( Y

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

' f7 J5 Z: c% b9 H3 v! X+ i! d

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

' k w8 Z; ^* l7 _+ a% e

. L8 d+ R- ]) _: ~

// 显示真彩位图

( Q! h3 n# A4 Z0 D* O

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

. b& w! a. J7 W- q3 H2 O3 b

: Z$ m; v# Z! }3 L

if( mFullViewTog == 0)

1 z0 n6 ^8 N8 _0 r- w

{

w7 i1 t% L* N1 L+ V

Wid.x= mDispR.Width();

5 v/ E8 {, q7 V9 z0 V7 B

Wid.y= mDispR.Height();

, B$ w# J8 l/ p" F; h3 C+ X3 E

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

2 Y* w, v" t9 c; ?% d* F: h

if( Wid.x > mpBitmapInfo- >biWidth )

; O5 l! H* M' f2 T5 f( A6 D2 I

Wid.x = mpBitmapInfo- >biWidth;

- D# l6 I' h- N( m; r/ Q/ D

if( Wid.y > mpBitmapInfo- >biHeight)

& R: w" b% i% R

Wid.y = mpBitmapInfo- >biHeight;

3 N0 ?! L% q: k4 L

- {0 N( B) p# s- R# D6 n* J

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

3 P7 X D' W {# l' I( S

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

5 z$ n+ O2 H) S. ]6 R' z( d1 M% T

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

" ~1 Z3 H- ]2 c: ?6 c/ n( b1 Z/ ^

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

- i' b% E! d9 l/ \

} else {

( c; E7 S W4 ]' c" m( o6 m

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

, w H1 o4 }( `- O

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

+ ] X! S7 n: @9 ?5 t7 d' ]

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

Q v( [9 y$ g! Q8 U7 y; Y: V

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

5 U: o- I# h4 w( T$ d; [

DDF_BACKGROUNDPAL);

' f3 B# [0 U% X* N6 r ?

}

7 _9 U- d- a) y$ L/ E1 }0 v6 u

}

5 Z1 j/ N1 R9 K

return;

' c* l2 {; {% }3 \3 x$ V4 F H

}

: Q6 n; D# p9 Q: L) h

2 r2 D F3 F' r9 g

. o# C! Q. }' v) m1 [, g- k+ q

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

$ N6 U5 V7 d7 y5 R( v; `7 C7 _

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

( B0 p1 t% s6 q1 R2 l

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

4 y1 Y6 J) q. C0 N1 u

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

% V5 a6 R% j/ G

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

2 A8 s8 O' x5 n

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

0 I* n: x. o5 V$ s7 _

; c- J" V V$ o. S+ l$ @

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

0 m' H: z& c M' C" C; p: O5 T

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

5 X2 l; f3 W; a1 e1 s# l

M* C( s9 l! h4 r6 |9 Q

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

! q Z( _+ _/ Y7 {+ f( k. A

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

- T( z4 w0 C" t: r- C+ L

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

' _9 l* v" X. h5 @! f5 O

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

% V% O# P$ `! W8 E# F0 b2 Y& d

。代码如下:

9 ~* J8 i) b* Y& @$ {# h

7 @% k D1 P, B5 c4 k) t1 Q

void CMainFrame::OnViewBitmap()

I/ L# J+ E- L5 R/ s

{

& Z$ o- H* l8 D3 T; _. a+ L. V8 X

// TOD Add your command handler code here

% T5 u5 B2 o& D

CViewBitmap *pViewBitmap= NULL;

5 f1 u3 |+ v, s* b( G7 ?; l

1 Q1 o/ |) e$ e# o9 U

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

1 N* ?7 U3 v8 F: i; d, @2 |/ E

pViewBitmap- >ShowWindow( TRUE);

% p( W- J3 a; m, E5 P+ p

}

. M0 w# E% |5 p; z: c

2 u& O2 u! o( ?% p

3 i3 C% E* f7 t

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

+ J7 t& o2 m; Z& T: f, u9 W8 T

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

" M g/ k5 @2 O4 v {8 V& v* V& b

/ J* d! T0 |+ ^. g

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

4 i. V. M1 A: U* E* ]

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

% d% b+ Q0 s! o' q) n

, }- M. N, E) m; d: v# |, B# H$ _

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

: p4 e7 l* s0 I4 Q$ V7 u( D

' t5 G8 w/ k* d4 [% o

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

) \ C' f$ G- Q1 S+ c9 j) N$ r

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

. C. J# s# a0 {- p" v$ M- V

# K4 f+ Y9 ?- T" U9 _- x

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

6 v5 t. `1 U% `2 g

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

$ ^8 `+ w: b& P/ j

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

3 G) n! {6 j4 h" E5 ^7 a

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

) A1 s7 Q, m; }

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

$ E! G+ P v/ W; J! f9 v. t

5 J- V% U: u ^; V1 U% g

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

* U' I" b- y4 y1 [9 r6 O5 `

就可以显示该位图。

4 F l6 L0 M5 Y) s

9 c+ J/ ^" P5 K$ ^8 J

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

* \/ Q3 L5 L; l1 P( J ! T0 f P1 w W2 H4 e

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

" v- a0 m3 Q) B$ M9 U( W/ U2 G

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

1 W/ s V9 L+ s: N8 R

真小,显示速度快。

- D8 U0 x6 _' f. D, i# ?

4 Y( k/ F7 M/ u. M8 Y

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

2 c5 p) _: l7 r

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

( Q; p( M, _4 ~2 Q" A

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

5 v% p! v l9 A- C5 b1 b1 l

; ?. ?% k* R( A8 L

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

* c2 h$ [1 g7 @1 c; x% o6 G

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

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-8-10 09:14 , Processed in 0.385236 second(s), 51 queries .

回顶部