QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

8 }( q1 g0 b; `3 T- Y

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

1 `' I# C1 u8 G0 W2 g

张义云

2 { V# i) R _4 X, e2 J) |

b0 G' ^: D, ?6 E7 l3 P) j0 F& Z* [

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

4 t" C2 Y* U$ {1 R! Z( o, G

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

4 V6 f& n4 b! X2 \

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

# R! Z! o' R7 p+ J b! `

/ B( V4 U6 l& Q! t

---- 一、BMP文件结构

. k) O/ E* H& y' V6 V0 j" X* ?

% u) K# c$ T4 ~; j& X* `

---- 1. BMP文件组成

+ n0 M7 |! d+ Y- R% a; x

- g* \# O; R/ a" Y8 [

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

3 d/ u% ]5 x z; Z* c- e' r

* x+ M1 m, l% M) U0 ]

---- 2. BMP文件头

4 F: E+ D9 T3 J1 e/ v& R6 @

9 V3 l: h. U4 B& f

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

1 k4 q' C/ W+ }% J' [- R; {2 J* u

" T& ]5 t/ R; }/ ~% j+ W4 o, D

/ Y5 A) l* H' v# h( A0 ]

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

% r0 `' u# b& M( R

% p! ~/ ] P5 l" d$ F2 z

typedef struct tagBITMAPFILEHEADER

/ O. D& c% @5 C: n

{

/ v9 H& L8 A) M2 P

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

?* W' H9 T- |& F6 B+ g! z9 @5 O

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

. h Z8 t& `: f# ?

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

7 t$ j. E# ?% O7 K2 u- O

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

, R4 G& _$ W K

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

/ [; P8 W0 e: r: q$ t) ~

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

0 ^* X% f/ P2 n

} BITMAPFILEHEADER;

5 V% `0 s1 J2 Q$ R' ~

" x# w; }, L; o/ ^1 G' C: B" H

& {7 u, J- |9 s$ w+ u6 `8 j7 {

---- 3. 位图信息头

# |6 H1 h+ c' l& x6 _

----

* x; d% N1 ]" q' J3 K4 t7 T0 `; ?

5 s# z8 I6 x$ B; m' {! _1 @ p

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

+ L+ Z& c4 n% a* c# S

typedef struct tagBITMAPINFOHEADER{

; i3 V* n: c2 U& j; D8 m

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

1 N1 p. X/ c0 S; I& ]( D) T d1 i

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

2 }: N8 q" S e& b* h' D

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

$ c: v0 a8 x. }

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

$ d1 F; l; T, }% M# l2 }$ c

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

: X8 l+ F4 a5 s- g/ M8 z

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

, ?( v- p9 a7 W; _$ k; E

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

. K5 M( i, n, g' |; k

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

* y( _9 h$ Q9 b3 A! s

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

3 S. b, C A/ P, s: |2 u

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

/ Y9 L, ~# }, x

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

C2 Z9 c9 y6 ~+ i5 p( x j, F- t

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

; N% G6 b \0 p7 u

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

4 J! ~+ t3 K- Z9 o$ l

} BITMAPINFOHEADER;

* `# W' Q3 N1 `: b

: Y0 Q' X4 B8 N- ]

" C, w9 s, m6 _( |. u# x5 z

---- 4. 颜色表

9 C+ M" j. ^* I4 D/ F$ h* Z

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

) c1 c7 ^' K6 @1 n* O* D' G& i6 t

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

2 C$ ` S, Z" k1 B- Q

- A1 f4 r! M& L. ]( D4 }

typedef struct tagRGBQUAD {

6 m( M( b+ x3 u% T( T1 I- E& l

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

* E( P% g# g9 e3 U) @

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

7 @1 x$ X- H" [9 X s' N

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

7 X5 Q0 @1 E6 Z2 w6 N1 q

BYTErgbReserved;// 保留,必须为0

* s1 ~0 \" s7 U, O5 B! r

} RGBQUAD;

5 L% b! ]0 Z" y6 u5 N' l. Z

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

! p# i& W& C: \$ A0 \/ Q; P

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

: d/ B4 ]" w- }* O$ @9 ^. f- ?

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

0 ^' V. U _" h5 i8 y

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

) W6 S Z* P+ m0 @

typedef struct tagBITMAPINFO {

# ~! G* J( q1 G9 y1 W+ T$ J3 O* Q

BITMAPINFOHEADER bmiHeader; // 位图信息头

4 w) [3 ^, p3 A

RGBQUAD bmiColors[1]; // 颜色表

5 `0 L5 J9 m' o. A3 B

} BITMAPINFO;

/ m; ~# G/ t- x+ [/ Y9 n

& N- a( p Y; R7 G

3 s% B& u+ Q# P' x* A5 s

' D, i# b# N* d% L

---- 5. 位图数据

# v! t2 D4 I. T' A$ O* t7 y8 N

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

4 x/ i; _4 `5 y5 h+ b9 ]

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

, {. G, I. }' s/ i3 G

o3 C8 C8 o- r! s# e4 F

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

) H2 a( ^! i! H% z+ b* J/ F

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

. d( `, Q0 p( W$ d8 J& ~0 U

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

4 M0 q4 X; r: ]9 p) t- o7 T

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

( ^( ?; f8 |! M" w0 E' I7 U% z

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

! f0 n3 i6 C% C5 t* T& P9 {

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

4 B3 A) e/ @ G" ]# N# i0 J0 P

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

/ r. T3 Q P' o6 M

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

' E1 M! u1 W, z7 K# S# S' F9 ~

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

. e4 y' M7 S* z0 l& k

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

* f( E1 c0 W; e" l4 W ]6 l

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

6 v; n4 Y6 B9 K+ h/ B+ b! {

DataSize= DataSizePerLine* biHeight;

$ y. b/ ^, ~0 K2 i, y0 x7 ] n

! { t8 w/ M8 C4 Z

3 G2 D( P+ E- V. i7 P9 j. V

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

6 z8 `: s, Y, h! z

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

: e+ {# q5 [3 ]; I$ P

" l e# f# l) E2 k; ?, f$ n6 e. v

---- GlobalAlloc(GHND,FileLength);

; {1 y& F: i3 a0 ?; R

" V% m5 _# b$ j& j# w: G- I, L7 n) k

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

0 Y( L, e D, C9 w* f) f. m! q/ k

4 v! ^, t t/ i) ?8 X4 E

---- LoadFileToMemory( mpBitsSrc,mFileName);

: y9 [. }. t0 h4 J+ N

9 }2 A/ d4 _" g2 O+ X( {! Z

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

1 h2 V0 [6 \3 Y8 S! Q$ X- ]1 a

; B4 E4 ?& x! ^, J& _$ `

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

( p" ]; h9 Z6 q

DC,

9 z2 E6 V* t* ]2 \6 L0 p% k; A8 B

% U4 e1 `/ G( p q

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

% ~ v: N/ P3 ^6 N0 j

p0 v3 A% ^, I+ Q+ T: i6 r

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

8 y- e6 s0 o* U; b# {

4 f! I J# u- P6 W' \

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

% O& H) [7 h# V6 }. }( n

% e- z, W; C4 S* S; f# N& {- l

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

7 A! I' r5 C& B. S

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

' J2 `; G' z& s' k W+ a4 X

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

I8 B. ]# \$ W- r% M. r

$ S# Z/ H/ o4 F, a( A

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

% ~$ ] k- B. @, E4 X6 Y- S

0 O1 o8 f. m& s. ]5 O- }

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

+ F( J& @0 }1 W+ X

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

5 I1 Z$ r- I! W( U- t, D! _! o

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

' g$ k. s2 V ~2 K |

0 K; W5 U0 Y* l

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

1 v/ P7 }, t% v3 \

. [3 F! T$ v9 s

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

7 N9 G3 L6 |$ e) A$ X

. I9 t: q( |9 B2 W" g7 ]

---- GlobalAlloc(GHND,FileLength);

" k& q. K# g' _# m6 g* e

4 I* z) \/ ?5 r# x! j# L9 K

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

4 J+ F+ n; T$ \8 G

* B& y( r. Y' P. ^# K

---- LoadFileToMemory( mpBitsSrc,mFileName);

* ]1 i% L; t" L6 r

* ~" @ w' w/ N: a7 c6 \' W

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

& Y& [. j1 T9 Z( _

7 W. Q. i# M, m+ {5 B* ?% o

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

5 h2 |0 k B6 g* Q5 r

& X/ a4 u. U2 i$ T8 Q# f

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

: Z1 F; m) [; q/ `* p1 U8 i

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

, h. ^4 b) V' j0 ~. r- ]8 D

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

# Q& f' X. R2 J3 u/ q

3 d1 V( ]/ P' W1 [

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

# v' X* N. j. W+ U8 ^

: ?) o- ~: C+ d% u& O

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

1 p9 f! t3 \5 }6 y0 ]' u3 @3 ?

( x$ X i& o: c5 Y: j

HDRAWDIB m_hDrawDib; // 视频函数

/ _, P/ s9 |4 g4 F! G

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

5 ~; f- @) r+ L& g

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

) ]4 Q% Z8 b( c

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

% V7 u8 G1 y3 f# a ^! p0 t

0 i9 ^9 `0 e8 N

, x6 u* }( F' T7 X7 W3 B4 O

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

% Y" c) Y# p% C! W5 G

---- m_hDrawDib= DrawDibOpen();

q4 z! U# {7 N

' r. L: Y- K8 y+ C3 V

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

, ~7 H7 {% f* X! ?" I

4 v7 H0 i, H. R$ j

if( m_hDrawDib != NULL)

1 @" }8 p% Q4 z; [# ~ [

{

8 r1 p0 H4 F4 G8 b% j6 K+ h' N+ O! ~

DrawDibClose( m_hDrawDib);

p0 r* A- e2 N

m_hDrawDib = NULL;

/ I! b v, d7 d9 N% Q& ?8 L' K" {; {( h

}

! w' n) A: o+ L2 C; a H7 Z

+ d& y/ y& q4 s) ?0 X% x s

" ~, Y- S5 @3 p

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

# q$ f6 ^) m6 `: ?& m

voidCViewBitmap::OnPaint()

0 `! G" X( A0 j( I, D* v

{

# N+ G& [0 v5 ~" A( a2 W4 I0 z" y. m# j- q

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

1 p% g. Q2 s. U6 W% g" i- r/ T

GraphicDraw( );

2 y. N8 k8 }: S! K) G4 B* a. h

}

# w0 ~5 F8 i5 J- a* B

1 w/ _+ I- w6 R" U! x* f

voidCViewBitmap::GraphicDraw( void )

. T/ _' j* F7 B: A9 p

{

# c2 H2 d1 W9 z( k

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

, f0 O8 s, N+ D* `

BITMAPFILEHEADER *pBitmapFileHeader;

+ r% T7 ?- L# u }2 k# ]' `6 a* B

ULONG bfoffBits= 0;

1 X l2 T' h V7 m) j

CPoint Wid;

% v9 [" t% E" w1 h, c8 L

: a( t2 A! n' }; l# Y: q2 U

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

0 L" g# b' ]4 P' `' v

if( mBitmapFileType < ID_BITMAP_BMP ) return;

8 b4 y, o' n* g# i& ]1 d9 Z

. @$ Y9 I( Y R6 {( x

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

1 f! a& R4 c" s# o

// 准备显示真彩位图

^' m' |7 B- V2 R$ c; L6 X, o

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

& s& C4 o$ F( L' Y" r

bfoffBits= pBitmapFileHeader->bfOffBits;

# g/ \, {: R- n9 p; _

% N7 D v: [/ B$ B u2 z) w

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

+ G- {) z5 q% C3 r }

5 X" C* @ |4 |8 ~6 ~

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

" Z5 d1 Z3 M7 G! O

{

4 _0 q; @ T5 S5 U! x& s, f

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

# a* G6 b, f; n O% u

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

' y: K% u; r3 {' |

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

* J0 _! q0 Y, T. S+ E* i1 {6 `

// 建立位图

& |4 ^: x6 A5 T2 D, m

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

: h# C. M9 X& F+ q

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

3 ]2 E% l" p! X. U: X; ^: j2 Y

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

& r2 D3 ^' d" u

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

7 ^& D7 ] a7 ?# y

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

3 |& F8 K' ~1 x% g2 C" I

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

, a% `9 m) c5 M9 P' H& ^

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

! H7 I) t x' R# P4 q7 f( f; b2 Q

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

$ A( z9 ?# j% Z4 a# {4 w/ ?+ Y

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

/ L/ B1 @: P, H/ u# o

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

# E9 W: i; }4 r* u+ T. w/ X

7 T! a9 p: g# U. ?. r' M; T, ^ \

if( mFullViewTog == 0)

$ ?3 s s# k* R4 s7 k- N! V( A

{

" S. t {1 A* ]! z+ M* o4 C

// 显示真彩位图

5 f9 o$ s8 h, ^9 ~* T% e- \

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

$ m" L _' D% g, b% [( s

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

6 j: H7 G9 u* J' x( o, Y

} else {

' [/ f( ^- A) G. @4 _

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

" P0 U `7 C# c6 \, F

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

' {5 M/ W/ Z- c4 Q) O6 ^

>biHeight, SRCCOPY);

! j0 X/ y7 J |& D

}

X9 V0 I( W C$ S4 C

// 结束显示真彩位图

0 _6 L" K, _% m3 D

:eleteObject(SelectObject(hMemDC,hBitmapOld));

, V w$ J: p( [" `

// 删 除 位 图

/ D% R5 i$ m# T& F: ?

} else {

3 r9 g d% r) \1 ]

4 L- k5 V) y: ^1 {! [: k

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

: y$ i7 i0 C$ _4 K

' W1 K5 a+ K7 q" p* d

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

8 j) y+ o# i1 k/ s

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

# w: u! z3 X* R! n6 C8 V

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

7 f. h) [; F$ v0 \9 c

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

' d0 T9 k) J( G% m

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

; G! w" | f; k4 F- q8 O

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

% J" W* C+ B& B: m

: @4 b! F& z5 ]3 l6 W

// 显示真彩位图

4 z% o8 g, y9 x

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

& u& k. i$ `0 ~

+ e8 m7 E* c3 x/ v" M" p K

if( mFullViewTog == 0)

8 M% ?6 |* \# G( R

{

7 W9 Z+ S' R3 z ^1 T

Wid.x= mDispR.Width();

) {' k: O; B% G& ]/ d9 y6 h% h% z8 J

Wid.y= mDispR.Height();

. `" I' Q, Y$ _$ v G5 z& T

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

p! z- S0 ]1 y

if( Wid.x > mpBitmapInfo- >biWidth )

: t" @3 R) D8 Z2 [: A& j4 o% T& Y

Wid.x = mpBitmapInfo- >biWidth;

, r3 W) ~2 r- P" F! m! o2 s- t

if( Wid.y > mpBitmapInfo- >biHeight)

. H7 c3 g9 b0 c: Q

Wid.y = mpBitmapInfo- >biHeight;

' J, g8 e& G5 F2 E' X

6 J7 n1 s9 M5 m4 x% ]/ X

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

' |) H' a5 E4 R' |

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

. @+ y, p: P4 t4 _2 B# i

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

1 |7 |, o& g i, A

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

7 D6 S+ K1 _% A% F. J1 V

} else {

& x Z9 `2 g: u& [( _" h

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

{5 ?: t, E0 ]7 Z0 k

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

# r6 n& {/ Q2 ?' k

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

0 R$ D! }) @5 a/ O2 s6 v

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

% \7 `; R5 X4 F: i: A# o

DDF_BACKGROUNDPAL);

. S9 N9 t2 Y; _6 Z; a

}

8 U! _0 y0 i$ E1 v9 |, v

}

& \3 C) b* j+ `0 A

return;

6 a( G/ N. j# Y5 x! w; T

}

0 ^: b1 ?! d9 J" U @

4 n' U. m( P$ i0 @2 D3 W, H

7 E$ w* z0 {4 o J' R

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

6 k. K: T+ a* R. @4 h( X+ E

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

4 U. a& Q, P2 Z. ~8 S: Q- K m$ ~+ r

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

1 t* h& ?" p3 c6 b! s; ^5 A

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

5 h7 R% w5 @1 \/ G% A

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

5 A0 H! l; {! T9 y5 X' a

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

% F, w) i$ \3 O8 X

8 q2 F; g& P7 b

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

2 K% H$ g: p5 c- ]% z+ }

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

3 F* G' H+ F7 F9 W/ A! G

# X/ L! o& C0 i+ O& Q9 I; E% I

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

; O% q$ g% i0 v' O; J9 }8 \

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

* p$ q* y# s ]* u

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

! }$ j* |8 _! ~* c1 k# _, _0 |

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

/ E* L( F4 h9 m

。代码如下:

+ x# s0 b% D3 A m( h

! O; S; _, d8 l9 U" ~; T

void CMainFrame::OnViewBitmap()

' b$ I4 m5 T# ?7 v$ x# D3 I5 u

{

' W% Q; n0 K: Y& }& _- ?

// TOD Add your command handler code here

5 j2 c! P# E1 ]$ ], U1 Z

CViewBitmap *pViewBitmap= NULL;

% `) _9 [, q' w8 h, P9 _

. o- d F! }( t4 I9 P. @- U* I

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

3 u9 B, B. Y0 O& p

pViewBitmap- >ShowWindow( TRUE);

8 ^5 K1 }0 l8 w d8 |% {

}

$ H) d+ j, A/ n% f. o& D# _

& V( P. S4 h3 F; ?$ E

7 ?/ b, `# f# J' F4 \0 p

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

! N! k U$ J5 [6 ?7 ~: k2 E

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

4 `9 K7 B1 u' h( `+ j9 b5 P! u

5 v& t m% D' x! B$ c- H* q% h; ~

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

* L) o6 A" T3 P9 C ^

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

! g( n1 O( o5 h4 c/ {

& ^. F8 z4 H6 W- A( U/ n* |/ z+ s

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

/ ]7 _+ D" W/ [) A4 r

$ ^# c+ b2 l# b( m; A

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

/ `9 b3 u8 K& h3 o9 [( D

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

8 a) i7 S0 I( f D3 e

5 W/ [7 z# k2 R. d: F

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

' @& U, _8 f* X: x7 o" A- A+ c

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

/ N( P0 ?. Y& M3 k! O" A9 L/ j1 X

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

; j4 I! P5 X$ G+ H7 H0 ]3 H: X

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

: \ T2 Q% ~! D; i

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

5 S f% j) \5 W* d: ]* h1 \' C

; l! q# L* l6 F

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

: f0 e; ?8 w; U Z* q! \. `

就可以显示该位图。

, S" ?$ C1 z- T( ]5 D2 {. m

+ k* {) P" }0 O$ B( A& \

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

# B. Z( ^# w" F6 V' a/ s6 d% K / C$ H" q2 K+ Y/ o* H

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

* k" s% }/ y/ e) C$ U5 g) g9 u# |4 v1 a

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

0 s7 b/ A9 W" N3 t" w/ C$ r3 H

真小,显示速度快。

8 H- I7 {- [0 _

. E* P# w% Y+ Z% l& {0 r7 ?

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

. e6 @7 P' [3 n& P

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

8 c: O) K3 T T3 o, k! K6 t- ]

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

) l* y1 w+ M( ]8 g

' M* j# P$ u$ U0 x$ a/ A" F+ J4 n) h

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

: m$ ^* Y5 {/ p6 }8 Z) 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-8-10 10:33 , Processed in 0.418389 second(s), 52 queries .

回顶部