QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

m4 O: D& B$ ^: V

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

, l: `% a' o8 J

张义云

% V3 G* u" Z! y! x3 ^9 `$ p8 a/ ?$ y! D

8 b) ]: Y5 ^' r

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

& Z4 g$ \) M/ Q& F7 C

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

; s) m# r5 c5 T) o( p& n/ x) W

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

1 E0 g( `3 W) m* m: N+ R, z) B; [

% M+ M8 F1 X3 R

---- 一、BMP文件结构

5 @" I/ ^0 {% v( ]

( h& Q. T. \4 ]" J

---- 1. BMP文件组成

! m+ J: Q9 R1 Y& |# L

5 V' c$ {# U- p X. t2 I

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

+ C0 N$ ?4 e/ s) H- V3 [, {" G

: Q: [5 @* t3 N

---- 2. BMP文件头

5 W3 w; q/ F: l5 F/ _' {: v

( |, t4 o; s: y2 P8 n+ x. l* o

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

/ m5 D: D& d/ E2 k' g

1 `# F- V2 M1 [) n1 P

9 Y2 q1 N% W* p7 |, L. E

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

* I( ~ `% r! Y( T) b

% R- J! m; `; [+ _( ?

typedef struct tagBITMAPFILEHEADER

- d; W6 _) ]( P. Y- L* m q- F

{

8 T: Z" _# J# A8 l2 }* d0 x1 l

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

7 r2 ~* Z6 ~: Z

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

* ~8 M; c& g* s* y

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

# q& j( G* k' O

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

% ?, Y8 c5 A5 A9 O1 I0 ] @' w

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

9 ^6 S4 y8 J2 p7 l1 a

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

% w7 ^2 I0 C0 m' v* x! G# w

} BITMAPFILEHEADER;

* X5 F8 y" N9 L2 ^. l6 @& I6 ]

7 a1 l+ \5 b' G6 e- M- S2 u

1 [7 K" \# g! S. ?4 T# n& [

---- 3. 位图信息头

2 z: v9 x* ~& s& ?# a, A7 T2 c

----

$ D, L# B/ V; \, o) `

; x6 T7 {% q9 @# }6 u6 _; Y

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

# B9 Z6 F5 c8 ~- C

typedef struct tagBITMAPINFOHEADER{

2 L8 A: R1 T! U

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

. E; i+ ~; F8 B7 q

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

9 ^, C8 g4 w( a# ^

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

1 P# J+ g O/ l' {5 K0 b, S6 ^

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

0 \+ r5 p; i7 c( I

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

( e+ j" s! c6 |

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

" A0 V' E# G2 O6 Y# t) H

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

, S p- i5 G% b7 ^! o

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

6 r- d* J4 a- c* @% S

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

; }/ s/ Z9 b8 {5 N! f

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

" k, s, C4 O0 B1 @; \( f# f

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

# e8 a* J: |0 N7 B0 X# O2 L, N

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

, c& y$ f3 n! Y

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

3 ]) E) k8 M v

} BITMAPINFOHEADER;

9 r6 f; k7 v z; Y3 T

" x: Z; P6 I5 s; s+ _

4 ?1 d8 c0 n7 f6 a4 j3 D

---- 4. 颜色表

+ B( Q$ ?& B1 }' E

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

# P9 R" {, L& j# O+ q/ G' x! V! @0 [

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

; ?! |: C/ A* s& [7 w3 {8 f

! k6 m/ V! j8 E) l9 }

typedef struct tagRGBQUAD {

/ [: T" J n; I1 d5 t2 D8 [. ?, }

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

0 K& `. H# Y! k! [% I4 J% I

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

) M* t% l* | G" S2 n6 I' C5 m

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

$ a4 B7 ]" P; N1 S& b* v9 S4 X

BYTErgbReserved;// 保留,必须为0

" `" |9 r' |) s" B

} RGBQUAD;

& K4 i6 a: |3 e

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

/ F9 j Y( m3 m# r B

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

# T1 H; y$ v3 H7 m# _ Y

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

6 e4 b W' s7 |8 b5 U! b# }/ x, I. A0 E

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

3 V9 e$ z1 U5 @+ B0 h0 ~: e/ g

typedef struct tagBITMAPINFO {

6 ^( U1 k( c# l' Q K

BITMAPINFOHEADER bmiHeader; // 位图信息头

7 a/ M- I7 Q; z2 m* P7 @. B( W

RGBQUAD bmiColors[1]; // 颜色表

% h& r: L- `6 o/ X( [

} BITMAPINFO;

8 ]3 ]) k( d4 J7 Z, D+ |

! ]' k7 j% j F

' R; {- b, D8 v: C

* i6 `6 j4 B6 Z9 D: c+ r5 w" I2 l6 }

---- 5. 位图数据

0 `& E6 O$ X: h

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

' `* l I3 |, O8 v

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

' }" i' J; w& o% m/ x. ^7 g2 b

# H" F' Y0 L0 l/ R" U& \

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

8 C2 p, B3 B" ?3 i3 m7 Y2 D

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

4 s" Y! @1 r& r+ M# {2 h

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

% R: e5 S+ D2 n# W

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

( A2 F% v0 W, ]9 x" T& ]

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

, ?& n0 H/ q9 f/ s5 l3 F

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

5 G4 }" r( m q+ ~0 J3 q

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

# G' f' y+ ` \1 r

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

, L" U% } m5 c. A

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

8 h! I' O" r9 r5 W

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

/ Y' m- B- \1 o9 C- ]

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

) U% {: d! [9 ^2 Z

DataSize= DataSizePerLine* biHeight;

/ J9 Y2 f/ D, s5 Q+ N

) b0 i- N5 h1 [! ]

9 }. b# E2 x1 B$ v* J

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

8 B& x& O! e6 |1 M1 |( D3 O' ?

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

S; J" p X( i) \- v( [) X8 D

7 A1 `4 F9 x! P' N2 P2 W5 H

---- GlobalAlloc(GHND,FileLength);

$ z$ \2 g8 b9 [

) l/ A- H8 R9 i

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

9 i; r( T; d$ _. l

1 D+ w" b. J# z! e! |6 s! v

---- LoadFileToMemory( mpBitsSrc,mFileName);

) g+ d; ]+ M- i: x; w0 r9 r5 Z

0 m+ P2 _( ^/ @! w6 a

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

( |! X# t" h6 t3 H) x( I/ P$ B

u5 ~$ S7 L* T

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

- v" w/ M$ e+ f6 y$ ^, N

DC,

6 a$ ^: Q' ~" `: ?3 R9 l

" Z) X; w; I# F4 r2 {0 G: d

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

2 P( i8 \% l! z r

& Z( ?4 [3 r/ o. T0 H; Q: f/ F/ Z

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

6 w2 c# X' Q. F+ \( t) Z. V

+ ~8 c" z. D$ s4 Z3 w

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

+ A4 ?0 K* N3 F+ |& \. l

. {% q3 t7 E4 }' @+ o* f' p

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

2 T7 B: N: O+ k8 [9 j: I

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

) C- k! R4 {$ o- E2 z

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

) M% r& k2 t- e T, J6 } d

! w+ I2 l9 q' M; O, ?

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

. d0 l c+ `; t7 e- S( l

, s9 n# W/ o) J5 @

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

" e7 R* d; L0 s+ m# Z+ q

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

5 A) t% S% H" P" C. V" o1 R

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

, z H( K* a# ]9 d: u

5 H$ ]/ |! o, b) N$ p

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

. T6 B: v0 f9 V' j# m% `

2 n( C) |& f0 \1 }

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

' O, j3 ]5 v# E r6 X

/ V& {+ E" W5 b

---- GlobalAlloc(GHND,FileLength);

/ h7 @5 e6 p3 O

$ |% P. t3 k, U, s* m/ L0 Y

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

' {: {" { U5 f2 t0 z; s5 c

* Y; d# q2 O" f/ M- ~' { n

---- LoadFileToMemory( mpBitsSrc,mFileName);

: P5 R6 F$ v5 f/ J; j. P

; u# w: v/ H& y

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

7 p/ O; E2 V5 U' Y( J6 D+ T! Q

- i# F0 \6 K! ^5 b* M' s% r& `, g

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

8 U+ i; b% p9 G* ]

, g* O- B/ J+ c" t3 p- k# _

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

( Y8 F3 k7 j0 M% g3 K

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

2 C, v2 N: Y8 u

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

/ ?- j3 L, p0 n+ e# [0 A" A

/ n) x! Z. H5 V( K8 z* c2 G6 v

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

$ g$ C! ~8 K% H) w7 `

" J" R9 u9 S! b, a& }

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

7 i7 L f( j- v. O

9 Q. R4 ~/ P3 ]. F' N/ s" a

HDRAWDIB m_hDrawDib; // 视频函数

Y4 Q9 S& z8 B& v% o% g8 } G

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

9 H5 e% w P% B1 F6 E

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

0 P0 c- u1 W" B8 P7 w* X6 s

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

/ ?/ o$ V+ W1 u

9 {1 J: A* t$ B8 Q' q" ^3 W; P

; |4 K% f8 \# M9 ?5 D# I* m+ _0 Z+ c

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

' f* C- Q8 A) a5 y6 G g# T" b

---- m_hDrawDib= DrawDibOpen();

3 }/ ?- t1 ?2 @' s0 `+ w

9 R* p& q$ L. \5 [. _: G

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

, D2 _) f& k0 P P' ^& e2 r

$ `- ^+ E' U& g9 \' w7 r

if( m_hDrawDib != NULL)

& y! O) P3 n, v1 z" w

{

: s6 k: S+ e2 g4 [& S' f6 g

DrawDibClose( m_hDrawDib);

3 f. E, p7 W' a, K& h

m_hDrawDib = NULL;

: [; }3 h& X' m n* x

}

& |' Y; l1 N; ` a3 B4 \

- Y4 Y K6 {+ b b

! Q1 A6 ?, j6 J* t- ~7 ]

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

1 Q. M8 Q- ~) e5 X

voidCViewBitmap::OnPaint()

4 d0 _/ ?$ X; q4 _7 q

{

$ O/ I" Z- o) v3 L8 L9 B, C

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

/ D2 q$ l3 T* D' z: {0 c

GraphicDraw( );

- {$ h* }; _, L# s: n; m

}

$ b( z* e/ k6 o9 f, I0 s2 s3 ^! u, {

. v8 ^: o: M* Q8 `7 e

voidCViewBitmap::GraphicDraw( void )

1 D0 A5 L: X% d; ^$ c) R! x/ f

{

$ l* a# l" g8 b9 B/ c

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

4 F% C7 c0 L- Z) f7 u

BITMAPFILEHEADER *pBitmapFileHeader;

2 L6 l- I2 R1 l* B

ULONG bfoffBits= 0;

p. U7 r7 B J* h

CPoint Wid;

; D' T# s" s, r- f! x( B) H

6 x2 K$ Z* f! |$ e0 E) e/ l

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

' g' t9 m8 U) C$ Z& U/ \

if( mBitmapFileType < ID_BITMAP_BMP ) return;

8 g( D8 b8 {& G, ^

9 N; Y+ E8 r( O1 \" v. y' C' E: a$ U

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

5 K, A! ~- v, d1 H

// 准备显示真彩位图

% |; S9 t0 E) D) t# `

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

5 @; D2 c* b# l. Q

bfoffBits= pBitmapFileHeader->bfOffBits;

l! W5 t# e u3 z) L* ^* \

) b8 y) e2 S5 |# g

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

& N" O$ U4 n9 S

5 I6 q, v2 I/ r5 s/ v

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

( b7 @6 P! t2 r m

{

: x. W7 q6 G6 b0 M+ s3 v

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

/ k$ H& j6 t# i2 H! E) T

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

" i# ^- x+ k# x8 K, ^

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

: b4 O/ _9 Q2 @& j

// 建立位图

# A' A, n% W" z+ ~+ ^

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

: o3 z4 Q h6 X

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

; L+ w9 G7 {& L! I% Q

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

8 [3 Y6 p. c6 f$ x: r3 x

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

5 W! Q) a- `7 r* q% T! O# h. g! S

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

4 @# q) W: D1 j) _

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

6 L+ ]: r) _, W/ |) _* k& }% |

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

: j: p0 `5 g- |9 b- l

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

. v% i C# ]8 _- A* n9 O8 M0 f

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

$ f7 R7 o9 d3 `2 G( Z% E* |5 o

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

7 H* F, M8 I j& v5 x Y7 e

. s( R2 {' T5 o: A" j

if( mFullViewTog == 0)

/ m0 }; h+ l7 e& C: A

{

' }5 F* @$ [ i" ^$ T9 T- |

// 显示真彩位图

. ]( M+ D' A3 j* s% [6 J

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

, o4 E, w8 v. O1 m9 U$ f9 X( k) X% y

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

+ j, f5 z }( u1 X, l/ n: a# g

} else {

8 b/ o: B! B# }/ @# L4 }

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

% s; v9 Q+ y8 w% ]9 G+ ]# z+ K

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

7 K) ~* r- @' }1 F* l# ~

>biHeight, SRCCOPY);

$ l% M" f& ?8 `! [8 f

}

) V/ `) Q# {7 l/ |& T1 I

// 结束显示真彩位图

$ h7 a h, _% i; V

:eleteObject(SelectObject(hMemDC,hBitmapOld));

0 H& g+ A, Z& h$ B9 U W K

// 删 除 位 图

/ ^. r" `; x' e/ E! o# S: i- Z

} else {

, y/ F% g7 b' p& [' i: `

" \; R, f/ M. ?; t

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

H! S2 {5 a. |1 u7 D8 T3 h

9 [0 X; R+ m8 N

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

6 g9 S+ H: \( Q! i; s5 W

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

, K) h/ Q% r2 }3 N+ g

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

1 r( i+ l( {7 J8 w8 O7 P0 U

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

$ S- w! }# r9 ~+ @. C" {4 |! h( l

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

' F7 k' K+ t+ H7 P( F! y3 R

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

4 m+ U7 G9 O, s6 d1 P2 ?6 p) T v

; I3 O! \! u0 H$ b& ^3 Z

// 显示真彩位图

2 [, i6 H) S6 d* v( N8 d5 s

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

* L$ [6 o/ {7 e" c' H

* L' s8 V* F0 Q& @6 Y3 f: y# c4 u

if( mFullViewTog == 0)

6 o/ n/ z, a7 a2 k! E2 G* n% [ T( S8 m

{

5 k# D2 ~2 c! F' B) J0 J; v, Y

Wid.x= mDispR.Width();

( _4 Z7 Q/ p, K/ n' \0 S* t

Wid.y= mDispR.Height();

7 p8 V* `9 b5 o$ S5 D3 D: O

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

7 J9 z7 s4 y& N

if( Wid.x > mpBitmapInfo- >biWidth )

% h* x2 D# q; K1 z% |

Wid.x = mpBitmapInfo- >biWidth;

+ C/ X1 U- M" ]6 U }3 j

if( Wid.y > mpBitmapInfo- >biHeight)

0 I7 C4 E3 L8 t I$ g& z

Wid.y = mpBitmapInfo- >biHeight;

2 [1 D8 J- r- ~

( D3 g* F9 Q+ q. f6 v

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

2 j& S& t+ d% t$ C- ^" J

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

I7 q* I' z3 a, I

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

[( a$ `2 P" I0 Q; i5 G

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

& `: Y: M0 {* |0 W) X1 q: E) h

} else {

! I$ ?. `5 Q I" N3 w) v# u

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

- ~( T8 `0 s* r2 j$ g8 R

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

0 D2 d4 f) _9 n6 I6 W* n7 M

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

/ B0 a/ n) y# P6 `9 Z

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

" [( _# w1 v% b) o) o4 e) h

DDF_BACKGROUNDPAL);

& V; F/ p% F$ z2 i' ~" \

}

: l" e5 w$ M5 G) [. F

}

: A" `+ _* }* X+ { C8 B2 E

return;

; h5 G+ J9 d2 C+ E6 C' A

}

8 |6 ]" C8 `, c q

5 N' [3 n" e/ m( R( `2 h/ M

& \# K8 j& J7 E2 z

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

8 m5 t4 t8 W; S9 j

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

! l% r( H1 c6 B' V5 L2 |6 s# D

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

/ l( g2 h$ Y: n& y0 h

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

; A, p7 M# `" g9 \, a. i. `" M

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

+ Q K7 O! b. ]

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

0 b: v8 y+ a3 ~. ^

( ]. l0 d* o! n3 [, o

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

8 @3 k @9 }, s4 M# n) K

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

' X8 @6 ]0 D/ l1 p/ U v

0 s5 j* N+ T$ N, S

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

- g$ a+ Q5 w+ z1 `5 F

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

0 r) T r1 E: Z/ y7 X0 S

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

" }& |/ [/ O% c

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

0 k# N0 E+ K6 j5 D% P7 O

。代码如下:

( K2 }/ y4 g+ r/ G( a1 L

& R4 j V+ p- x5 ~9 Q

void CMainFrame::OnViewBitmap()

& Y+ S" D5 R! }

{

8 Y1 n# h& f1 u& o: S

// TOD Add your command handler code here

0 Z9 n+ ?+ I2 C# M# ?7 J

CViewBitmap *pViewBitmap= NULL;

0 V6 H* O1 s p% P) y( F& v5 ?, o

2 d; z; i# Q- x% L5 {

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

& `$ @. n+ X! J* J' |

pViewBitmap- >ShowWindow( TRUE);

2 T9 t% I, e, {3 T% v% b

}

6 \0 X0 J: ~, F. ?( \( h* F& j

W+ C- T2 G9 P- }; L

! Y6 _: p; X$ `& ^2 l

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

. c \9 \% c; i4 \5 f

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

( K4 J& V" }% ^8 \( @5 y

o. a b6 \0 m; d4 t; }; l7 P

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

% h( ?8 |) J6 e1 E# }* t% p( ~

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

7 `" c# w, C+ c4 H, n8 r

* x8 K9 }% \+ ]; c8 @

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

: x/ ?- E q& B4 B# j. N

! Q" k" J/ D+ I9 u% K! I

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

- G- o5 S; J& s9 U; [% x

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

$ \: c1 W& I8 m( P5 ]

' c4 [! u. N k* h6 M# C

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

0 ^- N& ^# O/ e5 ?$ ~' F* Z, w

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

. W$ E! e; B! f! j4 {! c4 s, o

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

) R% u% a, w* U" Z1 L

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

( q1 k+ B2 }, H. D8 S

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

! ~8 [ F* J9 T" P0 H, {3 k: l8 i

: T& ], X7 H; {7 E

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

, \4 \# m8 L2 h2 K5 n5 N

就可以显示该位图。

4 F% @; S X. m7 }5 I

% g \( u o% B( G

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

/ b& z! ~6 c7 H* b9 y( j ?; r3 Y& V) w4 B

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

8 c) A3 z0 @8 ]% v( u! J* [1 x

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

# `' H! M* p- P- Z% @- }" M

真小,显示速度快。

" T7 U8 `3 B$ m- G9 u& K

9 ?6 j) g2 Y) _9 f( t7 K* ?, u5 T. {

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

' G: |) M! L1 {/ T

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

" o V# T: u- m1 i3 u3 ]2 k4 k

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

1 B8 @0 \% k E9 }

* Z4 [& _) I( {

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

. ~& }) v) w8 v* P& Z

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

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 08:28 , Processed in 0.443791 second(s), 52 queries .

回顶部