QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

. c2 S4 S6 k E- h$ k2 z+ { z. a3 J

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

7 X% d, c0 _ J! [8 f9 F Z/ K

张义云

9 A) g& n- @4 {1 [

; W/ I9 x- q# X, o8 d. B

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

. d0 Y7 y( J* |

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

& G" o- I) s+ g. c! o% U6 j% ~

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

O4 E. u6 v$ P# Z

5 T2 I+ Q. |% s, I u& o6 c

---- 一、BMP文件结构

% @0 \5 O' V& D1 O

?" _/ t3 w. y5 c

---- 1. BMP文件组成

+ Y q5 L9 \; z& [! Y4 I& R

& y3 a& L+ j: Q. O7 ]

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

9 c/ ? a: @$ F; ~+ @ V/ T

% Y e; }' ? y; ?, k r' {9 D

---- 2. BMP文件头

. b) I' o/ |+ @

$ `+ ?( v4 L# b% q

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

, Z! D- Q: ]0 Y0 C9 C& ~) ~) b

0 `# t" R! A3 M# x) z, n# p

, K) p+ `: Z1 M

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

7 n" r) b( l9 x4 v' U3 [

5 x6 ?0 d4 b7 _0 @3 p4 l

typedef struct tagBITMAPFILEHEADER

2 ~2 k1 p; j/ G- @# l

{

7 \9 B# ^( E, H

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

0 P: S! `/ f) d6 `9 F, l

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

! z& R( L6 N6 G3 x- J

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

; u) m1 |3 n3 y' a

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

2 n1 J% G( M+ ?7 A2 ]- u) |

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

2 q8 ^& F2 `& f4 F i

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

4 d J) r. u+ r4 l- y w

} BITMAPFILEHEADER;

k7 b6 |( J8 s8 o' b s2 K( \. {

/ N: B' K! C% f

; `1 X5 z, G" V% a; D7 F1 [3 J

---- 3. 位图信息头

9 |/ W# @, |; ? N6 U

----

1 y. H( g9 I3 W

. L: Q9 @1 M( Y* |

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

. H2 E4 ^1 \# R' u8 T7 h' F

typedef struct tagBITMAPINFOHEADER{

! [% _: a( K) ]& | |, i2 S

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

+ d8 {, v0 A& C4 L: [

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

2 y( V2 ?' ^; j* t6 {+ ]

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

; H8 k1 c( O$ ~: a

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

! W0 G! B; N8 e3 X- @ K# S: s& r

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

; l+ N$ g) Q& K% _

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

6 D8 A* m6 r6 M

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

3 f; r T( }9 l4 l, `! H @

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

* @$ }0 |) n* g! w9 H+ Z

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

2 R: a! `6 k1 a2 N# F" ~% G

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

9 N3 T8 P& h9 _: A$ {0 j

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

6 T# q! K7 | g5 m" k

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

~6 `# A. P" q$ q, b

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

, c+ R5 H1 w+ ^0 Y/ Z: S

} BITMAPINFOHEADER;

1 C3 t4 Q, j4 Z& w- W

" j. f$ R1 p8 Z/ E+ w1 j6 h

" x0 x1 T% \; O3 }" r

---- 4. 颜色表

$ r8 c7 F1 ~" o$ ]0 \. `& k

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

) C# A; G9 B' Z7 x# y

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

* O+ u6 {* e/ a3 ^+ W Y% Q4 w b

" h _, g/ R3 E$ S4 C4 b. \5 t

typedef struct tagRGBQUAD {

9 ]4 q6 u8 l/ n- J% j

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

& L4 D3 x$ f! ]9 _% A# b

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

$ g& g4 [* a1 C) L

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

. d+ N6 p. O( I4 G C

BYTErgbReserved;// 保留,必须为0

6 [0 z2 W( C, s- D, a4 G: n

} RGBQUAD;

3 t$ j/ A" d$ \# ]* q5 p5 {

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

; ^( V. f3 g) S) J0 A6 D

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

) W. I/ W- a D& E) g1 d- B% J

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

/ q* F" o+ E8 O5 [0 L

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

9 U8 K$ @+ Q! n) |/ {

typedef struct tagBITMAPINFO {

" _' I% l' q1 n

BITMAPINFOHEADER bmiHeader; // 位图信息头

1 n+ Q2 S) y. T2 n( Y3 k! I

RGBQUAD bmiColors[1]; // 颜色表

[% h4 K1 L3 j7 k

} BITMAPINFO;

0 c5 u, w8 K1 D7 Q4 U( t& @, k% j7 U

: w- \1 O3 P4 Z7 r& @( X. E/ A! Z

1 h! h% r+ u% D- b! ?

4 C8 x& B5 u* Q8 [, n

---- 5. 位图数据

1 `" @+ \+ Y2 S3 u

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

4 [3 U7 W, L: y0 Z' @" ^4 O+ P

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

6 o) H* z4 A, [* U6 b7 U( s/ O1 A

8 |- U) `- H: w( i( B

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

, U* |7 ?: ]3 G2 l6 n0 R. U! v% X; T

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

5 z. J/ V- K T3 A+ I

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

) K. n6 }. U7 x# D+ P# ]# o c8 v

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

) o% _. f! {, M. p, g& a9 ?8 J

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

# ]+ G$ [$ v% x+ E7 C2 u& v1 F

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

; @# g+ E7 |& B8 W

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

4 g9 F+ m) z$ Y

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

6 u8 c0 `9 I, t- n7 H( m. N$ ?

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

8 c" x2 O: l' U+ f5 r2 C

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

; x+ s8 u7 @; T" u! D" c* u

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

- ~. H% z" |8 X9 E; z0 X' t

DataSize= DataSizePerLine* biHeight;

& N" t6 E X. m$ L- k8 m! x

3 Q4 f3 J4 r- T, B( |7 f

9 ^6 e0 y" ]+ R) \; w3 @% v) ?

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

@8 [+ J" D+ _

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

6 N/ |* l. E: o) z. l

1 _: V) _; ^; H5 H5 T& G

---- GlobalAlloc(GHND,FileLength);

+ r. M. O3 _$ P; ]* x

: B* d8 X4 j/ U8 V( z8 l, m

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

3 f* h" B" i$ J T8 t) W' H9 ]7 {$ n

% w0 V+ O; \' X; `- U$ }

---- LoadFileToMemory( mpBitsSrc,mFileName);

- A2 W* L! D& p8 \1 N8 g( K1 E( d

+ J% ] z! e) O" F/ @

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

5 u3 u, } q1 o* j. r) Z

$ `0 u; Y3 p4 w+ B$ L

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

" u) l# N! Y7 d, v: `2 e

DC,

" [/ [5 ?, [& L6 U

w8 X* x8 t/ Z6 H' b- | C6 k

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

' B. b* X! t6 P$ V5 X' u

" b4 `. d0 h1 }0 m) o# p% n& L

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

" j; I' K" A' k) W" {

: M- T) l9 P2 `$ E% x

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

) i) d, V, Y% |8 K( w

- \- v' F: J# @, p I

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

7 {; t8 g& T. P

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

& u9 ^' ]6 @. l+ p2 [, t4 I- Y2 A

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

( o. N. r1 Q) s2 k, k

; A T9 C0 G$ M: @

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

) G) y* V/ n0 `% o- a* A- j+ A7 G

/ o# r6 h* x5 c" w- V" N

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

9 z: D! H: _8 s9 U$ [* z

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

! ~, S! ]; k+ n

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

& {& v* m' L$ r; }3 b1 u0 [

: _& r) x; j K3 p+ E+ ~: a! M$ _

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

+ k0 o3 C, P1 ?3 l1 }0 ?% x

/ _8 A! ], Q7 C! y& U/ h

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

7 Z L) R; j- e9 W H. Q4 K/ Z5 m

, r. ^ [/ R1 c6 g

---- GlobalAlloc(GHND,FileLength);

H/ X7 Y5 c ]5 d; U

# _4 G9 I- G, _9 ?. d9 x

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

( p. `( j# R# {+ b5 K1 g

. B; R2 v6 d( b. q4 b' Q

---- LoadFileToMemory( mpBitsSrc,mFileName);

( {, ` u7 m7 x: _ d/ v) K( T# c! U8 O

6 d# W; N9 y) x9 l$ W

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

6 a5 W' j6 L& [& @3 O1 K/ X$ P

$ c& s7 E) \0 s! d% w/ A5 u- {3 X

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

' V {1 i2 n! ^. d

- `- j0 T$ T/ ?, B1 t5 I

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

- {$ m/ c( Q9 @( X# C+ m( \. V

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

# y N$ [5 u; q, A+ _( p3 n

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

0 C) W, v) j& h! @* h8 r

: b; S1 z% l$ K- M2 m. e/ Q

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

8 T, w* f( y3 Y, j

8 M' v( W' B9 i9 B& S' l

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

! f- I: Y# _; F. Y

d; W$ F1 T8 u: M: N

HDRAWDIB m_hDrawDib; // 视频函数

7 L; F' M( f/ L# Z

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

}1 N) P! X* D1 J- A/ ~' p+ I

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

- Q& R ^0 o8 G- Y

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

. i }) ~9 Q3 l- O

0 e# f/ y" e% `' F% a4 K

/ Y+ H2 C: \4 W

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

3 \1 @/ W. K% K* Y5 i

---- m_hDrawDib= DrawDibOpen();

! j8 a2 S9 G/ {9 [

) {$ }3 o7 R+ ~$ w

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

1 a% b! A# w! L2 b

1 ~% g# w* k0 s. g% K5 y

if( m_hDrawDib != NULL)

- k* C& ~9 ?: J& B: Y

{

2 |& m+ y+ x7 E) Q

DrawDibClose( m_hDrawDib);

# i6 Q% L, T$ r( |9 I

m_hDrawDib = NULL;

1 g1 f( o/ i& D; E! n9 c9 J

}

+ [8 W5 e+ W' j: [$ p! U

3 W) I/ \, q- | ]

6 @0 [" B! d* U `6 W4 @

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

3 \0 {. ~5 B0 y" D4 I1 L

voidCViewBitmap::OnPaint()

/ o7 R: O$ j6 f+ p

{

- g. }2 R3 R, e* h2 i. {) H! u

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

9 _4 A) v" A/ w4 ^7 c( c% H! m

GraphicDraw( );

2 N% B% i- e' }3 h/ h

}

4 I z# d* L7 ]9 g) b0 q& N, J

, w# D9 C1 d( C0 _; A

voidCViewBitmap::GraphicDraw( void )

9 G3 {& T3 u% [" K: X8 {

{

( R0 d+ a( Y+ P/ z

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

) ?& k+ B6 r. |2 M; w6 a4 u

BITMAPFILEHEADER *pBitmapFileHeader;

( m2 A+ o1 ~" Q9 z& ?2 m. B

ULONG bfoffBits= 0;

8 ?( H0 B0 `2 _6 ]

CPoint Wid;

4 C7 B' G- C& B; ?; P( }

7 X1 Q( D5 i9 w" d

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

% U7 |' B8 b/ B

if( mBitmapFileType < ID_BITMAP_BMP ) return;

) z C: F+ r) f

8 c( H5 K" b# X" b2 F: g) t6 A8 h

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

4 {- d- y/ N5 I

// 准备显示真彩位图

5 N. h3 _% b! l4 k, F$ }$ R

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

- w2 g r' e( o7 Q

bfoffBits= pBitmapFileHeader->bfOffBits;

# J+ A3 G2 l/ e$ j1 U" ?8 S0 t

9 L* D% y, ?3 {7 y

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

( j/ n; R8 g8 o

0 T' F( j- _" y$ P% A6 F

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

8 I9 H2 Z* y. F$ p. M' m

{

; S! n: ^* Q5 y& T- e" h. q

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

8 c7 T7 X7 L/ u9 L. B

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

7 C% l. c. K/ [& |5 l1 @5 U

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

+ |* [2 z7 h( j- C/ [3 l

// 建立位图

5 G2 F" ?# O1 T7 l* Z. Q

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

7 d. e+ e2 v# ^+ v3 Q# h3 q4 J

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

; J2 \, X% l/ s

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

1 o) f" p, c# g8 p- `5 ~$ [% X7 N

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

1 `1 q" ]7 Y- f

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

) ~, S3 R& Q4 Q2 O

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

0 p' R% b8 i4 {* N* d! x

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

) e& N; T0 Y# N- d- C" M$ x

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

: F1 t/ G" T2 _. ^6 F

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

- X, G! h. y5 {4 q

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

% S# R( k6 `3 q" @* q

P0 Y6 ~! ?8 R* [

if( mFullViewTog == 0)

* @2 h8 s# [% H. H# j9 t

{

- H0 O1 J/ T1 W$ v5 L- h& q

// 显示真彩位图

% A v' X& |; x- P3 K$ W

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

/ C2 e! A+ \6 \1 b! U

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

) d* G" b/ Z7 |0 p5 h

} else {

! Y( @; c* t1 V

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

) D$ `7 V+ w" t4 o* s+ o7 T

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

. j' }9 ~3 K0 o" K

>biHeight, SRCCOPY);

, C! J0 ?5 s/ E* N+ G4 {3 p

}

9 S8 J; x, s2 N5 a, R+ B

// 结束显示真彩位图

: c7 t, h8 D7 P; s4 d9 z' @- E

:eleteObject(SelectObject(hMemDC,hBitmapOld));

, p8 Q) Y- `8 p; ~

// 删 除 位 图

# L% {6 h/ M% I3 _

} else {

5 ? ^: I5 `: n. p- j

" X6 [! S) m7 l1 l

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

+ e+ Z; q- p& L9 K& X2 e( E) R# f( \

) q$ W% t- [3 {

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

0 k* h, {$ n' s. D

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

5 f# G: \* u0 E# I# {: s% X7 J

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

" _/ ]5 C0 B( N! S5 d: X) k2 ^/ ?

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

+ `+ I+ _" d% L9 z* K2 S2 C+ R$ n

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

7 u3 u" }. C7 X

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

$ A9 H0 S7 z- P

1 @- o* W9 P4 G- J$ t/ S2 N2 w

// 显示真彩位图

( t! I' O, n% P5 m% w* s" W- S

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

" W7 h" j& t5 x9 H% \% K

4 P/ D* _$ `2 E8 y, S2 W. b; v

if( mFullViewTog == 0)

! N( t7 k& l5 @6 z% I) M$ ?% J% k

{

: I7 b+ ?0 I* Z' @' q

Wid.x= mDispR.Width();

: m @& M: x7 |1 ~8 N5 E: Z

Wid.y= mDispR.Height();

- ~2 W4 D* w( `- L. D

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

% e# x5 G& w* A) {2 B

if( Wid.x > mpBitmapInfo- >biWidth )

1 p3 `, P/ v- v; {; A

Wid.x = mpBitmapInfo- >biWidth;

/ {5 J3 V) O0 I& H& V& m$ y1 }' k

if( Wid.y > mpBitmapInfo- >biHeight)

( _! _0 H0 p; t7 u" j& v* x0 w4 S

Wid.y = mpBitmapInfo- >biHeight;

& ]9 W; l% ]8 Y- S5 T4 T; x: \

6 ^0 d6 r) Q* b8 K+ W' x

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

) P& ^& b* ]8 e; M8 q/ e. ]0 ]

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

6 Y" U: N7 {+ M* B8 ?0 s% q

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

9 J0 q6 }1 H p

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

2 y S" w3 a8 H$ F2 h3 j. S

} else {

4 h j5 I8 N/ Z1 o; w

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

8 o3 U4 i2 {2 H% W) K) e

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

) b" g; Q$ N' \' w% }/ @: {2 W

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

8 Z! ^8 d. \% |3 z; U8 x# A. g. E

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

. }2 h- J- A) t! x2 w, ]; N

DDF_BACKGROUNDPAL);

& Y" O: Z4 e5 z$ d: ?9 E+ s

}

0 p9 p" Q! X+ v4 ~: O

}

* L5 y9 d& @4 \4 l U

return;

* T; u( n5 P% D' i# ~! A4 j3 i

}

0 g: N: {1 B& m3 R2 Y

4 h( l" R' y7 \- l

5 W9 q9 K9 G4 \

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

! P3 l; c( L1 |6 Q7 A8 K3 R2 E3 a

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

1 }% ]3 h. q1 d$ g5 C( x) A

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

0 L; `, C8 I/ L% z0 b7 G/ x6 p" Q; A

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

# O+ f) ?5 T3 [ Z3 k% j

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

1 I0 Q; }" N& G1 G: z% H; D

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

0 a0 k& d1 b: ?; f

# s& Y, R- y& f2 O* Z

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

2 F! m' B- a& B

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

! b/ T5 \. z% L

[( g3 i7 a2 z( Z5 l+ P1 a0 V

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

6 ]- x" y7 p3 m$ l

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

% m6 a, q! a3 j

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

- W) Y9 a! C* |- J

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

" Y% D1 X4 D E' e

。代码如下:

- Q: [4 A0 A7 }

# H7 @* h+ {) e- ~% ^, K

void CMainFrame::OnViewBitmap()

" B- Q9 v0 c4 X

{

2 C- J f- K ?

// TOD Add your command handler code here

" F4 ^) o: Z3 x

CViewBitmap *pViewBitmap= NULL;

' S& _, W3 y; d5 w0 Q3 m

2 P" e5 H+ Y# {% k0 [

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

, A) D8 F; B# l% E

pViewBitmap- >ShowWindow( TRUE);

! t1 c1 a7 m j) C s7 i6 k0 [

}

* i# y, ~8 K$ A9 B3 x" x: ]8 ?

5 W/ z6 `& _1 e8 F

) Z$ W# [' |3 \( ]

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

4 P/ ~8 j1 A8 y3 A7 H$ X! A, |

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

2 R4 t5 T* H/ m# [- [

# v$ t: z A& ^3 w5 |* h

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

) b. F: I6 ~. [# [

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

2 ]) Q( [5 K( E- b) \

$ Q. }0 s; b- r Z! _& p b Q8 o6 Q

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

" N4 W3 O* V! L, ]' T5 Q) \' A

B6 h3 W. i- g2 S5 x

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

$ Y. N, C' N) m6 M

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

I/ W* [ V) W6 q* X" r

* Q3 V0 d" N$ q2 t- c9 J

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

P! P/ ~( C' K& L7 N" ?( f

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

; z( h1 W- h( j8 d; l7 d. {

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

+ `* ^; a5 L1 z) V) U

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

' l4 J4 w2 T! Z

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

2 s# V6 [+ k& r$ K, M

4 ?6 x) ?3 U. i, w1 J

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

' F; H1 I6 p: U! P- f3 Z

就可以显示该位图。

S0 f: S( D. N0 v4 T6 ]5 `5 z

) p5 D- z8 j* Q$ F

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

" d" Z4 C; ^. \* y 7 \5 ]2 `3 t; ~3 U) ]

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

) ?: y( w% j" l

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

: B9 V& J1 P% s* F* p2 _9 O" H

真小,显示速度快。

3 Z% A. d% w" l% |

7 Z, g- {+ k" @- H

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

' F6 z! e- {5 F

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

' R& I' `# w1 s9 \8 E _- e/ {

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

2 O2 @9 G; ]. G+ _' s# x, t3 B1 C) I

. d% Q" \3 [5 P4 k( R5 x

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

7 A; y) A d" M) V q

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

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-18 22:51 , Processed in 0.411213 second(s), 53 queries .

回顶部