QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

' G& h* g% A/ I# H' {

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

8 s1 A5 D: D/ ~6 o8 V: B) s! B

张义云

$ N' R5 D& H% R6 H0 C& N9 b

; Q" Z4 ~, S3 U& h1 f& {& T5 J1 n

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

, P" X, T. o& K9 z

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

- O, t# \6 y6 @# m

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

9 N6 _$ i( g- x( m0 \7 l; q% c$ M3 r

/ l5 j8 _7 j2 j3 I% Y

---- 一、BMP文件结构

- t) m5 s' j7 X) Z/ m5 w

+ l& U# A9 J; e5 ^( Z+ q

---- 1. BMP文件组成

# }$ V& b9 }" C# V9 } U' ]9 ~7 }8 |

0 o0 e$ [- L# H( K/ \/ b! m

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

) {6 w* n' z5 @* U4 t+ v$ g

; E$ { b2 e5 N5 f; G

---- 2. BMP文件头

; ~3 G: H% e- `3 |( v) i1 t

5 c0 i5 B* i6 o( @+ P8 E, Z

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

; U0 o& W4 W# h ]3 e- E$ i7 k

$ B' T: S+ {2 T, L! F

' @: s1 H. Q) T4 W$ a; i

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

1 s6 d4 _5 s1 G7 s& x1 {

* e% f, H' i8 E" K2 X

typedef struct tagBITMAPFILEHEADER

% A& f5 w3 j/ P% s# W8 \; I

{

3 A6 ]0 X6 N& m; \+ Z4 ^0 c) u& O

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

- q2 E5 r. b) m/ {

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

% e% v0 W7 `) h& ^$ B1 g8 v

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

4 C1 v5 m! c+ ]1 P3 H& a) h3 |

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

' E3 z ]' o @; f

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

; K8 e7 Z! A/ ^" H1 U& c3 r

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

- t" L* v/ b1 P. X- o) m

} BITMAPFILEHEADER;

7 ^. ~/ z9 A y: ~+ u8 l# @

' Q6 n: m& B4 i3 ]1 g; A' i+ C

$ a& G; ?- ^- k9 H" X3 E, d2 S

---- 3. 位图信息头

. [; i! t. Z$ |* ^9 f. c& p

----

' G$ A/ ]& j9 ]7 ^9 t

9 ]$ Q) V6 p9 ]3 E) S- m4 r

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

9 ^, k2 a# u% r

typedef struct tagBITMAPINFOHEADER{

2 X0 z5 S8 v# L/ m

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

& C! U6 A% l* x4 Z2 a

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

3 g6 t0 e: F# k+ ?

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

& v1 t% k g6 k5 B& g7 \

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

. j- F( \/ W- b" s& r9 z; h

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

. e7 ~3 |* Q1 Y0 v: n

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

5 a- P; p" p. T' @0 k) ?& N

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

( W) l( c5 K- Q1 O

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

) R8 V6 T" `) A# r# Y- B5 U/ U

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

" a6 j0 j3 m* Y5 B

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

& f, k$ b8 I6 G& j! q) D+ {% g

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

+ e) m1 u% J1 I8 N. N

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

- n+ u- w2 k, r, q2 {" M2 m% A

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

3 J U: s; G3 z, A& J& X4 v

} BITMAPINFOHEADER;

/ J( W E, q+ E2 n* G

) X5 V* v2 T9 m# {9 S- a0 F2 f

% K& x0 d8 B, C

---- 4. 颜色表

) n7 c# A2 x' r; h+ Z+ T7 f' W

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

$ `$ K3 s* i5 p$ R% v A; I" C

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

[0 A. _5 q: F$ q' S9 q2 P- o

6 m, d+ n- `9 J+ S: ]; ]

typedef struct tagRGBQUAD {

; {. Y. C; y8 t5 z( F

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

5 y, B" ?4 X; Y& R3 m

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

1 G4 A y) N. D, E% o0 T0 k

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

% o" B' v& d d$ v4 z5 y

BYTErgbReserved;// 保留,必须为0

' V. ^) H6 w# z& { j

} RGBQUAD;

0 r2 L' Y0 X& T+ U1 }/ r' C% F2 R

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

& G R: F8 Y5 ~, G$ `# r! C( g, K

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

" T9 v7 t. O5 i% w

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

& E/ {) Z" b2 Y2 Y: {' Q

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

8 z. k; U0 ^; W$ k

typedef struct tagBITMAPINFO {

- }3 e6 ~# U( M0 f9 _: f

BITMAPINFOHEADER bmiHeader; // 位图信息头

2 e1 f- M+ W+ y' [: i" l( t

RGBQUAD bmiColors[1]; // 颜色表

) P) c5 D- ~9 R+ x0 G& y6 J; L6 m

} BITMAPINFO;

, v* i% y' W4 x3 h

0 D9 M) v8 u' Z8 Y! v

9 R* t( J& l* H% \

& Q0 s* u5 ]1 Q( ^4 Q

---- 5. 位图数据

" l4 ]9 |& a. c1 t# S% Y8 X& X" c

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

/ w; f$ X1 y6 o" n" X

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

0 n% N q2 u! y0 P; c" p

6 s) V7 E3 G/ Z6 ?5 K- w' R

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

* y, D6 l4 C' T. e% g5 ^, n: L

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

( C2 `( ~3 y% c% M! m

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

/ G( d/ |, @4 O3 ?3 z

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

0 y7 C/ d! l+ F! B5 M

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

' [+ q3 Z& i: ~: R( _9 a) f3 V

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

- l- o4 a$ D3 n2 o+ B& p

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

8 s* O3 t* f0 x# J' `, R

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

- e! M2 t' ^: L& U1 H2 ?" k9 y

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

) ^& w% C3 P" A9 ~

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

0 l7 f8 {" K2 O

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

* N/ H- p: v) K& P0 [

DataSize= DataSizePerLine* biHeight;

4 U( j' V9 n+ g3 t

" |5 I6 U: c* [

% `& Q/ d4 W, ^; F

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

& m$ {- d& M: u, f% h5 t

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

9 t, W( S; {0 T1 K0 \

# G6 n; r7 E( Y+ A' R' O9 v7 g2 P

---- GlobalAlloc(GHND,FileLength);

4 K4 @2 Z _; o6 I

! O9 @7 b$ ^6 R# {# @2 r9 W: G k

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

% k$ a5 Y! j; |- J+ X% Q3 ^

5 b+ V4 W9 ~6 m0 U, D

---- LoadFileToMemory( mpBitsSrc,mFileName);

' p u3 P4 j- @- D$ z$ `4 Q9 t

3 p7 L9 j4 T; m/ T( }

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

2 J3 J+ U1 w1 ~6 P

" y# N3 g# j- c; U$ s3 Q7 P

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

; ~; q- B& I$ z

DC,

' l. q/ r) }' ^) ?

0 C }6 n( w2 X

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

" ?0 ?2 m+ O7 D

) d+ P4 D* l3 S E

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

2 F" j. ] v8 u7 Q) ^* k& F

1 ]( s z1 b+ L7 u9 |/ m

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

~9 \, f& u& z: R1 q# `

' }) l+ G P0 h' [& H( \

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

& ]' L- f3 o f. _

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

! F7 V9 \$ ^. b; ]+ N* }0 i a

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

1 W( S0 s5 k; P4 z& x% }

" d* }& N8 M3 l

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

; i/ e. {% _: b

]0 P- T" _8 w& X

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

3 d2 e0 o7 n8 `1 ^- C

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

+ w) N5 ]' A4 r6 T, _

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

7 ~, W3 U+ j# r# C% K! k G' ^

$ ?) G0 X' c- ^ U& \

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

4 X) X* w7 ^* h- c

4 O9 M# _+ J( O( b$ I6 E: d* S

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

7 |. x2 X% t! m4 d

. a$ Q/ Y c3 W2 u0 A, E7 B& n

---- GlobalAlloc(GHND,FileLength);

' {) {% [( W3 Z6 A& i" q

. o2 Z# t: P% D5 x, @: ?! l% M% d

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

4 A8 U0 z1 l+ W) f/ V$ f

. o: R; [) ~% F3 l$ A9 b

---- LoadFileToMemory( mpBitsSrc,mFileName);

; K2 [( @! U; \8 V$ V

s3 N7 r5 W, ~2 O5 d. O0 q

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

4 p; V: c5 ?9 N" y

. }! k A# C" J# a J3 z2 M- {

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

* I9 T' Y# `) o" }

7 W& M. i+ D2 Y7 i$ C3 k) s

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

5 ?& M0 J% r% n# E, R

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

. a6 K# `% u1 Z2 V& ~! x

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

6 S& X5 v9 I; D$ u% m, A) p: J2 M: D

- r# `! P) ?6 r4 t. _

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

2 I2 g- }7 k/ N7 O& y5 e) R3 s

4 ]* w& U% ?% U6 X1 Y

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

% P/ }% G' U. v m1 ~* ]

8 ?! s! L4 |; ~! ^" w

HDRAWDIB m_hDrawDib; // 视频函数

6 g4 I5 @2 |* ~

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

4 \3 k5 t0 [# P1 o) M v

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

/ u! B) S! O/ M7 Q# ~

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

: ]7 \% `3 v% @( @$ Z7 \

' q6 s+ k3 W/ ]6 l$ F Y0 J2 T/ X, \

! e( I4 K9 T( Y1 Z2 L

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

' b5 ~2 d& D3 w) x% ?

---- m_hDrawDib= DrawDibOpen();

1 B) A- f# f" F

! v) d! q( G8 U) U( Z( e

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

" b+ R& p7 ^4 B |7 U+ y- g

5 ~/ ~! `1 o: P2 j8 w+ A

if( m_hDrawDib != NULL)

, }: B1 R& q* K/ m8 h7 {4 s

{

/ ~' I ], M' `& r/ y* f/ B5 `/ G7 l) Q

DrawDibClose( m_hDrawDib);

9 x' C1 b8 F7 j! X

m_hDrawDib = NULL;

; n0 E$ {/ j* b9 V* f5 i& F( u

}

4 a4 x3 S; R; U# F5 W; Q

9 K2 g' z& x8 O9 ^- R: }, x8 |

4 @. r2 g* @8 T+ v

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

7 Y7 ?& D' E+ Z

voidCViewBitmap::OnPaint()

( _5 N0 z& m4 ~

{

" D, C! G1 |" C$ I4 w+ R+ L

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

: O5 z3 _" u, ]* L1 s6 M) Z3 T

GraphicDraw( );

z: W2 e& C: a5 g* c u& o" J. k

}

* g$ d" o/ E0 L3 L+ z7 l8 n

) U6 d& v+ h/ F0 M9 {, t; G) @

voidCViewBitmap::GraphicDraw( void )

4 @0 L, M/ O- L3 P

{

. }7 A* M4 _8 Z+ f0 _6 S5 f: I

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

. E+ W, ~6 J) h1 q7 o

BITMAPFILEHEADER *pBitmapFileHeader;

% C( T' |, T7 K

ULONG bfoffBits= 0;

( ~2 D. b4 n8 Z! V

CPoint Wid;

' s9 E/ W; [- r

8 P" @; N( i0 D% ~: ]. U8 o5 u" S

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

; d8 ]" S' Q+ ?9 g' X1 M

if( mBitmapFileType < ID_BITMAP_BMP ) return;

3 K( x$ W/ p% H

( N7 V8 `8 ^& G5 H& p/ E. j" M

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

- T( b2 y- T4 j9 P4 N) G' c. }$ s

// 准备显示真彩位图

- B$ }" I, t& l0 s; {, v

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

9 V4 x$ y+ d( \

bfoffBits= pBitmapFileHeader->bfOffBits;

; t9 K& Z9 j. h6 V. L; s: t' C

9 K$ f' F! n4 M1 d5 H' b2 f) u

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

( ?5 }. O& o) I1 x8 v- k6 e% Z. S: K

+ O w2 f0 e4 f- O$ i8 q3 f" l

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

! D, _( h1 h) j

{

) b" F; | ?: o8 Z1 R

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

7 r7 L& @# x1 R, M

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

# N/ ^2 d% E+ u6 i; x$ i9 S2 {

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

5 i6 i5 P. j' K }

// 建立位图

3 R, J: l/ M w

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

" Q3 J$ Q* X& V$ u

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

* n. ~7 V1 D8 D1 a7 j# ~3 A

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

% I6 B( k" r9 {

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

7 k, q. ?, h, N$ F

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

1 i) I1 Z0 l1 S6 @! J

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

5 I# A7 @1 E$ _. _. K1 V

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

# f) ?" I9 p( a: U0 m

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

& @1 Q: m- j% W( z6 U' e2 A

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

. g2 u5 N+ U: K$ p

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

% k; P, U& M) p U( I

; h5 ]9 D6 F, {2 t* H2 M

if( mFullViewTog == 0)

0 ~9 T: d/ o, ?. T7 T- \

{

- q2 v+ f. k" {+ u9 l

// 显示真彩位图

6 ?* `8 ]. P; o* u

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

# O9 P' d, z. W1 n% ? w ]5 ]

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

/ g7 O }; J; B! Z/ _

} else {

m3 z" U' I& r& |

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

3 k; r ]: P l4 W/ j- @

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

3 i% F. b. s# u

>biHeight, SRCCOPY);

! q! g+ j8 L B) f# Z4 ?! T( T

}

1 C+ f6 O T: I% L6 V

// 结束显示真彩位图

5 q) K( r3 Y6 c9 J

:eleteObject(SelectObject(hMemDC,hBitmapOld));

K$ |! @1 l$ M; k; }

// 删 除 位 图

' \) e9 H) z$ L% B# a9 @8 u9 h l

} else {

: Z) d' ]* E% `6 `9 u( f2 I9 l6 }% C

' N- O# G( x: ?9 W0 v [& b1 v- A

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

) g/ U7 c/ `0 n( s g" {6 D& u

% p! P0 M, M1 U6 l- h$ t

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

9 |/ g% q5 {+ m6 `6 F! u2 u

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

" f+ J$ \- {4 g) x j8 O

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

1 Z* C# Y. o. x6 Q& Y

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

& g4 i) Q( j& R

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

: [8 J4 ]% ^& h' m B. v- J

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

& V, |1 }1 C$ @# n

) _% V* {8 o/ Y& I9 d3 L* R

// 显示真彩位图

8 W! f; @/ D9 s) v/ {+ C# l2 `

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

7 {" ^& C4 \5 c V* A( c# Y7 j

; r* s2 b1 r% c5 ^& t' e

if( mFullViewTog == 0)

1 K( I- R' d6 v) m8 M1 a3 C u

{

: y1 _# S) }" Y

Wid.x= mDispR.Width();

. i( {5 t& a* S/ T1 y

Wid.y= mDispR.Height();

t+ E1 e+ r! A' p1 E$ Z9 n

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

4 z5 `( R7 j( x% c! b

if( Wid.x > mpBitmapInfo- >biWidth )

0 T9 U/ C0 |) K3 i, C: {5 F( K

Wid.x = mpBitmapInfo- >biWidth;

* g: y: N& K% f

if( Wid.y > mpBitmapInfo- >biHeight)

& j' J( F# M* _8 ^/ ~

Wid.y = mpBitmapInfo- >biHeight;

& I, m# G9 X( w; J* k

( c2 S! l0 T p5 e! i

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

( H/ y6 E: J0 f) c& l( {" j

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

' u5 z% L9 \2 K) k; y$ M7 B% [6 G

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

8 P+ |* y" I$ \7 o6 k+ p4 b

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

6 v7 C3 L' `6 q) \6 W$ E

} else {

$ z% r9 n1 m: \4 Z6 d4 R

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

# b& k6 Z* y' T; q- f2 e2 n1 G

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

- n" j I6 e9 T9 m

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

) N# A, T. o. d+ I' ?

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

% N8 d: F- ]+ w$ K; k" L9 B

DDF_BACKGROUNDPAL);

8 V2 l( \8 {$ X) i. L! D

}

l4 N) D( C3 x6 U& F7 E

}

7 b% f6 h" O& P- ~% O4 J# O6 p( y$ a

return;

* u. u9 v% r! d

}

$ u6 g2 k+ B; ~7 ]4 G; A

5 x+ T7 F/ e) p3 @0 Y3 {% Y; M

' U& E! d" P1 K5 G

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

! c7 X2 z! L+ F5 \5 q

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

! f# G! m; b) m0 X: l0 L4 N: j

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

/ Q1 A# a; ^5 }- y# |& A- d: o

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

6 o4 ]) R+ u# k* H" ^7 c

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

( i: s& C' L- Q$ Z+ p5 K2 w$ J

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

2 E, T4 N- N: Y+ `+ P" e

# ?% k* U" X' X) u

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

' E) }) A* \# \. N- A

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

. b. m l2 Z4 |' C l* s9 u

F) N& L3 d& N& a6 ]

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

8 ?( }# a) G* x3 d l0 q# |

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

! p" f+ Z4 M$ D- d7 @) n; q3 H' Z

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

- g" O: V% Y; S* x; |

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

3 @. U( K6 B) E' x- U

。代码如下:

# O+ l, _. X$ ~5 D* Z( c( i

8 |8 u* Q2 y$ r8 H. n

void CMainFrame::OnViewBitmap()

- I+ s" p$ Z* h4 z" c3 w* b

{

9 F7 s0 i% i) M- b7 |

// TOD Add your command handler code here

7 B8 z! e# Z# L

CViewBitmap *pViewBitmap= NULL;

( `: H! j7 Y9 V& `- s3 e: f

# `% q. {4 X/ Z4 o

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

' D* C" ]7 A2 Z k& z! o

pViewBitmap- >ShowWindow( TRUE);

/ y5 q; I" i/ G+ P9 a2 I

}

" s% V1 p% X) ?; _! C; @) K/ G

+ E( g* ]/ P2 v# m; X9 h

; V: C9 \ r$ O: H( Y% @7 e; Q

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

8 k2 @ E, }9 E0 e8 H8 F

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

" U8 V: [- ~& Y/ D$ J6 F' x1 `6 j

3 O3 H/ [7 v# z7 @" f3 s

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

$ W4 }$ _- j$ i$ u8 a/ j- y

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

6 I0 O7 i3 F2 d4 y) f; e6 v

, d6 `& H. N* Y& u

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

2 k- G& F) W3 S2 L$ @' U3 c* v @

6 Z: n9 `# U: v+ q

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

5 s, k( y! k# \- X# R @

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

& f+ l7 _8 [. n1 B. W* V

$ W" Y; Z7 ^( y, d' R$ V/ T" u

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

4 T( r/ I3 g a% @5 C6 I7 W

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

) P9 G2 M0 A* K* z: x5 W8 a8 ?, y! y

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

- I( P4 m9 j# u0 x, u6 w8 z

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

4 y6 R' `( A9 D

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

6 X7 A2 ~7 Q1 e# w

" f$ k8 n5 k2 z6 A" h, G$ h1 l

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

6 l9 H% m' v; e4 Z C& S

就可以显示该位图。

! a C& w, w$ N* y; p1 ]

# S/ \) J/ q% B9 a1 P& ~

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

: p! t- g( j: E# M2 E! @5 G 0 @+ f1 V* V- o- D! g

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

$ c8 j w5 }$ J: M$ [; t8 m

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

1 i2 Y L o: ?6 E

真小,显示速度快。

5 v+ c: _3 j- K, F7 U

+ E y( f7 p, Z1 U

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

; r6 a5 {: X3 ^1 @5 `: S

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

" Y6 ?/ n, K8 K" \1 d

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

& n5 M* w& b, \/ G

; ?/ D4 X; o" c, T

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

+ @ h: x; c3 ]/ p5 W) A9 P; l1 R

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

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-19 02:58 , Processed in 0.376769 second(s), 51 queries .

回顶部