QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

) N) V2 i- C. g* H# j6 a1 O' m+ w

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

" r! O1 W# v1 z3 h" l1 S

张义云

. F2 X# }( q {; z7 }2 r+ r- o

4 V8 k* Z: [, D2 _1 u) T$ a

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

% T c; i# R4 g, I& X

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

/ o4 O' b2 q" q8 B

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

$ N% _) d0 m& r) s* u/ [

% j6 k: M3 n3 S7 S+ c

---- 一、BMP文件结构

* \. `# j4 n) O }- L0 m

7 Q, `4 v# ?6 y6 |- J0 M

---- 1. BMP文件组成

# [$ g& d( r" H$ Q

% K% a7 `) r# s; M9 X1 u" Z, w/ N

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

1 |( k2 o" ~7 T) c# x5 ?/ G8 \" \

) z8 ~2 O. g6 R4 T7 `( |: n

---- 2. BMP文件头

J, J0 u/ R0 H: {/ j

+ \0 ^- w: G8 y: {& Q d" V* P

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

7 B) f3 ]/ n3 v

. Q! z" M. `/ D! S9 ?- L- r( t

5 q- E- S7 c! T

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

" p3 Y7 |& c F' Z" r

* H# K6 V3 A0 i0 ~2 Q' x" s

typedef struct tagBITMAPFILEHEADER

& N) G/ E5 @4 o# y9 F2 e* S

{

, ?0 z- R5 H& {

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

* d% ]7 r1 h y# m

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

7 j5 R* R) G& _ u2 ]

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

5 P4 {2 S7 ^6 f# Y, `+ K7 q b

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

8 e# r1 `5 h) i: D

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

& h! | e- a" W

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

0 {% C f$ F* ?6 x: f7 i9 v' |. i

} BITMAPFILEHEADER;

' M8 ~( ] h- j7 x0 I% g3 z: e" c+ k

% J( `' S1 P$ o. h

3 W; W, Q" H0 M7 B1 ? q' r$ f) A: A

---- 3. 位图信息头

5 Y6 u: B5 k2 g& {" u' j, V

----

% G( A: y) B9 _8 {

4 B2 ?6 \2 b" e9 v5 i) ^& X

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

$ j h" V6 D. |8 N

typedef struct tagBITMAPINFOHEADER{

6 Z2 I9 a, a0 V. ~5 O& x$ Z

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

, K. ?1 l6 p7 t; }! I

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

0 x s( ^2 n: q- I: L

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

4 f8 Z L5 k9 w0 m( L# w4 G7 c) i: j

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

6 \1 m" b+ H# U, p

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

0 [4 j6 H" r: F) I) [. ]4 u4 U

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

/ V, ]' S* F& N

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

% d3 f: S/ k! G9 Z0 f, b0 W

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

8 L8 C& X" I/ d/ c

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

; c; ~0 T# ^( {- a ~$ y7 W

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

# S* y/ N7 O9 |9 x0 @2 L; ^. D9 b$ p

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

$ r. m- R) V" ^. v' i8 Z$ Y* M

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

$ }# J# v8 L2 p/ ~. K% }4 X

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

& f1 }" L! i8 E) {0 s

} BITMAPINFOHEADER;

; e% q. b' {0 T! ^

1 q! K6 A0 B7 u B/ A

5 c0 {! _( [" C. n) f% a1 _

---- 4. 颜色表

2 H# o$ w2 ^% D, @2 c

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

7 a! q5 x6 H8 J! x" a

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

3 s9 }& M2 D% h1 U% k* D* p7 k

( m% A: E! w( t. z7 W1 P

typedef struct tagRGBQUAD {

$ H+ P5 `1 i- j( G$ G7 g

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

# w' n' q9 T/ E# r; r& h

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

" h A) b6 Q) ?) U

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

4 A' q$ o% v% Q# p* J5 H. j

BYTErgbReserved;// 保留,必须为0

" |6 K3 D# _+ A, ]% p

} RGBQUAD;

* p8 x# }0 Z# h0 p2 t v

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

$ M2 g5 q1 A+ ^4 I

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

0 z8 p" ^& X0 r1 ~

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

; c/ u6 n R1 e! [# ]5 F' J# {

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

x1 B7 Z1 F5 w; u5 w+ a

typedef struct tagBITMAPINFO {

% N5 M) R( \6 f+ p& u# k

BITMAPINFOHEADER bmiHeader; // 位图信息头

9 ?1 I1 ?5 R, w2 j

RGBQUAD bmiColors[1]; // 颜色表

, m' k* j0 f! {& `4 z8 ]: N

} BITMAPINFO;

) }6 @0 H6 \, s3 R. d

2 d* d9 V% U' n4 g8 C) c! C8 R

+ ^) D* U! ?: n* o7 l

) S4 t' P5 a6 c! d9 Y/ z

---- 5. 位图数据

5 ~" h6 k8 i4 g% X& V. `. w* W

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

! n5 }3 m. i/ ^# }& ~8 z

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

2 a' q+ a. O2 d# O, I

6 O1 E- g6 \% j8 d6 f

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

/ U0 B2 y; _" X4 Z5 K( p6 Z! E4 P

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

5 J6 M# W; W- }) f: D, f$ V3 g5 R4 \' s

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

4 V D E& T2 I2 f+ W: f

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

* E/ m0 F* f x2 ~! x! w

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

" s4 [2 [/ o& i! h. Z5 G

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

, @ M4 k( L5 J/ m. Q8 W

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

6 i, h* C( ^. r4 v! M

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

1 k3 ]2 ?! L* s

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

- A a" K/ x$ D6 ^5 Z. S- h% g

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

: M4 U9 x4 i0 ^* A1 E! P. u" G$ A

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

0 x/ g- v& t5 j8 v. g

DataSize= DataSizePerLine* biHeight;

+ C: V' Q3 ]2 h) V0 k+ m9 H1 S8 }

6 h7 g& U% {/ l S' Y( H

* j; n: D/ b* K% L, j5 j

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

9 Z, i; ^5 N5 R6 A# F" x

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

6 k, m" o2 v% r+ O

y3 q( k: n/ C" b# Z* C( ?

---- GlobalAlloc(GHND,FileLength);

" c" {( f; U \. `6 M6 g

) V* {; P- h; s" K. W. i4 u/ y

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

" N9 ^4 ~/ K6 z. P! J/ }8 P3 A

; H$ J$ C* E3 _3 F# }7 ?/ Z6 z4 F

---- LoadFileToMemory( mpBitsSrc,mFileName);

; Z/ V2 L, t' H C Q. s/ g+ h1 H

$ N1 s/ v% n/ h: f

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

' \' d2 T9 m, {) {4 L

5 p, J% L2 S! U! A2 T

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

' n m$ h. w# X- f

DC,

& Q9 l; M. v2 I( A5 b

3 E. N4 v4 V. P& l0 }- G( r% u9 ~# F2 X

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

* p4 ] O9 A; ~* W# ^- H# Y/ \

" o4 W1 G' p$ O9 s2 }8 B

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

) J( L; f$ V: ^. J; o1 q

7 p- ]3 q8 @) c0 e; ], J/ I; V$ [9 j

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

+ E! n# Z) C7 a: m! b" } O. e3 A+ N9 J

/ |0 p3 H& D8 R

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

: D) S; E* D- j5 f3 s# R

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

& w% {! Q; f8 D1 T, t# F2 |& j

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

' l# P5 M/ y7 ?3 n+ T5 L- V5 j; m

* S7 [. @1 W! r) y( f1 ^1 [

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

! O1 s7 G. n: E9 Z; q) N# a

7 E% X8 x. n2 P$ f \0 H

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

5 ]3 ^3 Q1 [( i) y4 o3 V+ q7 p

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

+ d5 H; k# u' [- _

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

6 [8 q6 u# d5 E

, ^3 W8 L. [, Q4 M

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

# o5 J9 d( C' }( S2 a& ~

" ?8 j6 p; c3 I) N3 d: B) @! S

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

" R5 P& L* R0 M' p8 o

7 @- \* _0 l. w' _# a$ v

---- GlobalAlloc(GHND,FileLength);

5 |- q) N4 S5 h& j# X% {& |! i d

' c) r4 C; y) u( }( G' \$ b

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

2 q7 l5 D) D- h9 M1 M0 m

% h5 H, p5 q+ e' x# U

---- LoadFileToMemory( mpBitsSrc,mFileName);

- S4 S n. b U% F( Y0 P

9 Y* m1 p8 h5 p+ u: Q) S# R

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

8 r6 }; f$ F0 F8 f5 C/ c

0 f( [5 } ?. x% B

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

$ S6 n7 _! a5 m. D5 y

. _& g5 X# ]8 ~' L: i- Z

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

2 o+ `8 I( Z+ J+ y6 b

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

& i& ?/ c# [. p" l" M

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

( ]8 L1 o. v9 m$ f/ c& O

" g6 n5 o+ I j1 @+ n0 C& u! L

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

9 d# Y( d& A0 G

9 N2 H: \ T6 z* h

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

& }0 |$ O+ |, k! z: c' j) f4 q0 K

" z, X4 Z3 L- J- m

HDRAWDIB m_hDrawDib; // 视频函数

i0 x+ n/ K6 o

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

% u; d% _( O; }( c+ R1 x, j

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

6 `0 M. ~% t# h) S* a0 M N, H5 Q- d

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

4 E3 r* [ s3 q6 Y

+ W/ t0 p9 z* N& ? l2 \

# T+ F; `& i) N' x: K% f4 E

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

: j% y5 ~7 o3 a5 _' B

---- m_hDrawDib= DrawDibOpen();

0 j! w1 Q- E: [( `! e7 n% T

- j$ J* |; C2 Q' C+ e

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

/ m5 H0 G: T* J& m9 a$ m

6 ?+ b* ^5 ]. y( I" F

if( m_hDrawDib != NULL)

: Z. k R2 Q3 i: F" I* n$ e/ h

{

: [( Q [. g C, w9 u) H

DrawDibClose( m_hDrawDib);

6 d- R Z1 e1 R w2 A

m_hDrawDib = NULL;

+ L% G. b! Q3 _9 F' |: _. K

}

( Y% g* h9 a n" s# _% Z% v$ L

/ o9 |9 ?& V& j

; m; D, B2 i$ {5 Y7 X7 G

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

) U/ \6 m5 Q# u- H! M, W

voidCViewBitmap::OnPaint()

2 \) n K* _+ u

{

! S- r1 X/ C% ]# j% p. j' M

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

1 c3 v9 U7 }& o) ~2 s% Q

GraphicDraw( );

$ U J ^6 c/ w( u2 d& V5 Z

}

- O. a' ^6 D1 {& S

: k/ N1 u& |- D% n4 i9 {% V

voidCViewBitmap::GraphicDraw( void )

4 E0 b3 ~1 ]: W1 h; _6 g# }

{

$ U8 s" X- L/ E; T

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

* l6 n0 P/ J0 A: m

BITMAPFILEHEADER *pBitmapFileHeader;

! U/ |& T8 X' q' Q z; s( K( ~7 v8 P* L1 J

ULONG bfoffBits= 0;

5 p9 G5 Y9 }9 d- c4 t8 D' n: D" y$ R" u

CPoint Wid;

9 r) E3 N; \' P: x9 D: T

; ~/ ~, a. a# {% s1 \1 S% S

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

1 M2 k7 E$ A/ h1 j

if( mBitmapFileType < ID_BITMAP_BMP ) return;

. C6 r/ g- r' c

2 |0 j0 r2 p& [, W

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

4 U8 c- M+ U; G

// 准备显示真彩位图

. E2 z3 }5 @2 y

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

1 m+ ^0 I* c! |% @ S0 @

bfoffBits= pBitmapFileHeader->bfOffBits;

+ l( s' q# q. i, X b' W

. g- F9 q5 k) C, c/ H: e3 c

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

/ V/ T, [ }$ A

( Z, i/ J& I" L; g% o

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

; \+ Y* F0 Z8 o0 ]

{

0 y7 o, f$ x+ A/ w

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

; ?$ e' a9 n3 C

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

8 k1 @) ~. b' O$ [; N

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

Q/ q$ A! n7 ]& @4 d

// 建立位图

; [# P; P; I- r$ ]

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

1 D* `2 e8 g; b

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

9 h& {# J4 ~3 R3 `

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

$ n, p% y2 s: z+ f9 b

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

; K; v8 F# h" I5 Q# ^* D

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

, K: e1 N z9 q8 ?

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

2 V3 h) [, C) Q$ |& y( Y; I0 f

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

% I( r. ^4 j! _- I* S% A6 t) N& o

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

/ m! D! z; W; p$ l3 N' y

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

/ H5 c8 x. k8 \% i- b, ?

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

& ]7 N4 x. K# ~; c

! a, L1 P3 W& F, A: I6 Y

if( mFullViewTog == 0)

5 |& A& f) P$ L T9 @' Z' w2 D" v

{

: F: b5 D" [. U) G T5 H

// 显示真彩位图

( i9 o7 H/ \& j. M9 H* {

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

7 }- |6 T) d9 ~3 J& z$ W

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

1 R1 y! _( @2 J; U5 }4 A4 M3 c

} else {

( I! _& m8 s, O, {

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

/ K G1 F$ v2 U( e3 f1 j

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

5 c$ a$ p& g- q- |7 Q( C

>biHeight, SRCCOPY);

/ E7 G' M. a1 `. t' d

}

4 t! n0 l1 ?4 ~' [: V j

// 结束显示真彩位图

" w2 X5 D$ s% r4 A" n+ U

:eleteObject(SelectObject(hMemDC,hBitmapOld));

8 U- D( Z, M; E5 x

// 删 除 位 图

1 F2 m) D' o7 c1 A

} else {

) n+ V! w; T8 A' u! k; O8 x/ R

* [8 e6 B& Z( U6 d* t) E

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

' d6 l" E5 I- I# d

* r2 Y( e4 D) |5 Q3 X# }

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

9 u' k8 x. i* P2 e& z2 {

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

$ S& r( t( {7 ^

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

$ w. E0 L" E3 k$ A

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

( V/ I8 y" n9 b6 k

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

/ F( D8 n2 M7 S

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

{+ y: p3 b0 r+ j8 C( |: k

$ P5 E" i& j6 h M

// 显示真彩位图

3 M" z1 F/ ?& g/ X0 ]0 ], X' e

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

& E0 N" N& \' I+ g- H8 z) U$ l) K0 `

* J7 W- T: A$ Z5 b$ U8 C

if( mFullViewTog == 0)

; I+ t% x D b6 g" w2 F0 L

{

; U) T: v$ Y2 ]1 v4 z

Wid.x= mDispR.Width();

/ c. o, |4 H1 {9 Q0 j) B: M* C2 `1 _

Wid.y= mDispR.Height();

: @2 O' ~- T& m9 z$ d

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

" A3 j& T: g# G) N6 ^# Y

if( Wid.x > mpBitmapInfo- >biWidth )

" \8 d. d7 ?, F

Wid.x = mpBitmapInfo- >biWidth;

3 E( l& K' N$ G+ Y* I' j

if( Wid.y > mpBitmapInfo- >biHeight)

" p) l6 E6 k9 C: i

Wid.y = mpBitmapInfo- >biHeight;

( ~! J: e5 Z& X: W7 I; O

1 V9 L4 d7 `- w& {- t

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

: ^+ S0 ^# ]( M6 x, A

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

- o( P+ Y/ v& g2 j

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

; B6 j( d1 s* T; x

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

; L" f" C% @& K, c6 ^0 f# n" ]

} else {

% I0 A/ D! `& U; j5 o& e

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

6 ^! v3 O" Z, b, {

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

5 B0 c" Q) j1 c3 S$ y- b

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

) A# ?9 f+ c4 z0 L' }, C

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

: p t8 y3 |" C" P8 g. g q8 \

DDF_BACKGROUNDPAL);

p- |4 l) z, w3 a2 w% [- R, t/ |4 ]7 l

}

. i6 z9 `! ^2 x* [; j. c( ~

}

4 X! g/ f# Z/ i& o: ]6 Y

return;

4 q/ l; s* s+ r

}

7 n% M' l+ g& c* }2 ~, y& u

4 z4 F. }# g+ b; R; x/ w

+ v2 W2 q/ \! A4 T1 w

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

9 r3 E& d. L3 K3 A

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

6 B% Y }: `# l9 t# C: {

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

5 F/ V# c1 A! _; C5 @1 {

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

! c% @6 z/ r0 v6 t' \9 z' w

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

9 @+ P3 n1 d4 L7 C6 ?$ C L

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

& z \" @; A6 u. X/ t% q) x

* c2 q4 t2 ?3 U# d3 n

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

c! t6 I( D& ^0 D/ a8 T

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

0 V J0 }# k- ^5 L

- }" r6 w! x; k: k7 S

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

# r( c5 J8 l' e D1 J$ c. |

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

4 P2 a( c w+ t- d. U6 p

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

% X, q, a" b* w

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

5 f; Z% K+ _' V! N( v& y

。代码如下:

N6 l1 _- A" v: d3 u$ z+ l( Z

: D }1 D7 T5 M" a, v" }* U m

void CMainFrame::OnViewBitmap()

3 j( J* }# C* `- K! T0 ?( N5 Z

{

7 H& M/ Y9 \* s: V* p

// TOD Add your command handler code here

9 Z; w9 S- w7 W) A# S5 @

CViewBitmap *pViewBitmap= NULL;

. T& `/ y) ~0 P. O" n' T. ]

2 l }1 V2 ^. L2 b

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

% z, L/ ^" k$ p

pViewBitmap- >ShowWindow( TRUE);

7 v/ q4 g5 z# G/ V" s5 @, I3 j$ c

}

* p1 K e- y" g

3 ^/ M% o1 u3 z9 h$ u0 H

7 F& [" w$ ] }

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

, h0 a/ h( g2 f* m

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

& {- i5 _! l J* ?

V' u8 \. I) b3 s0 \

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

2 y5 L, F5 U7 B3 p8 c

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

, Q- q6 }/ o+ T/ v! d- ]

% M9 z3 A, p0 b% a# v' n! |/ ^

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

/ x K5 n% K1 `* ^

) ]$ [* n/ y5 h1 E; {1 P

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

- N) Z$ g& [3 a

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

1 Q* @7 T) n3 x! b

1 E1 Q2 F/ R2 ^* ?/ S7 ]. m

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

7 g. H4 i8 a8 o0 p

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

% o: p' e0 v1 ~4 x4 F# z

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

* a5 g, }" L% v6 E) Y& p3 C; p

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

4 G& B ^: E" F$ O- z

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

2 v% s; O% I: {) r1 v3 a

1 ?0 R. l% [3 C0 Z* B5 \

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

6 f. \$ E: g' E! H3 X5 l

就可以显示该位图。

5 H9 `0 [( {1 x

& [, Q* f, }, _

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

) @5 O: g" v8 g 8 ~" F1 h" G: u

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

7 k: g9 x& n/ G* f4 t5 |( h+ G

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

+ G3 r4 z1 P1 _) m% D( `

真小,显示速度快。

. S( ?; S; l5 F; G! A. h/ V4 o/ J

7 t1 M( E6 l! Q' e: l$ m, d

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

`3 \7 ~' f& Y0 y Z4 O

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

, D- E9 z( j# G5 {) j

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

/ z0 j; C) }! E; {

' }- G& t, e6 T+ }! N! t

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

. X; [3 C) }- Q- o6 M7 {8 k

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

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-11 02:25 , Processed in 0.497703 second(s), 52 queries .

回顶部