QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

; g7 Z" N7 P# A- L& `

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

8 X2 e' N. V" M5 O

张义云

( b( R; @0 K( ]- S2 [$ K; Z/ D' p

* l3 o- d4 c% C3 Q5 N

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

- X! \& N: |1 y% f

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

% w& d F7 u- y; l

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

0 c+ n* u: v6 a% M" c

_- C4 T- b; `4 \0 }2 ^; j

---- 一、BMP文件结构

! F. p- A' K* E

* P# m' o$ W! f; A9 z7 c

---- 1. BMP文件组成

% [, h" i/ ]$ F; C

7 U7 t& ]0 x0 M2 [( @

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

' z$ I; M: M! E2 t. f3 N

1 F5 f) o+ \" F' G4 k0 K* \5 M

---- 2. BMP文件头

7 O2 n s. N; @. i. k/ ?8 H2 P

- i' @, B- H6 p; }6 r7 z

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

; m1 m" ~1 k0 q9 R0 Q2 H

' Y0 t7 }$ R! ?8 e& s/ I

' c' [. H) i- `% F

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

% F1 n: }; e: Y. V

: `' G6 U3 C% |2 i4 V* O$ _

typedef struct tagBITMAPFILEHEADER

" t$ x* I1 H/ l4 P# H7 q* \) q' E

{

2 X) s( t9 Q6 U" y: a u

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

G% S' P3 v+ |! y! ]$ A0 h) t

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

9 B) z% f' D/ w8 _

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

2 W5 ]% i, s* N3 K* t1 D/ u

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

* ?& ?" d: p7 o: E" [

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

; H p0 O- F( Q3 ^, X

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

! ~" n. ]; u7 j9 {, P' C I4 J

} BITMAPFILEHEADER;

: ^: [2 s; @3 B% [3 v

7 e. Q" V: K5 s1 W

% Y! J8 x* X: L# E! n* U

---- 3. 位图信息头

6 k$ g# B, t; a: L8 J, y

----

: ?4 h% f1 d0 L: `' M

9 Y0 w* G, u( Q0 S9 r* i

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

9 q. n; u1 l4 P, N5 Y$ c% `

typedef struct tagBITMAPINFOHEADER{

5 C* N- Q# d! W9 E# v

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

b- V* j7 C" ~$ K8 w2 x

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

( q; S7 _2 @; e+ U: a" w1 y

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

; F) ~3 T s) l& j5 o t: V

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

9 t# `6 {/ }" e

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

! ~: G8 g3 {' z2 ^$ W

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

5 W7 a/ J2 j: w, [0 ^$ `& ^

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

; j9 k" E1 n+ E4 @8 T

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

7 S, t* F7 }: S

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

) |! g1 B% v2 F. q* D6 k$ Y

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

4 E' G) F0 F) ?2 u# e, a

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

9 d1 b9 S; C* T w& S) P& H5 E

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

3 Q* y, b8 A& ~, c9 J- b4 S1 H6 h% W

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

6 O" K7 p( X7 l" ]! G1 q

} BITMAPINFOHEADER;

$ P# |4 L6 x+ I1 T5 ^6 t2 A

% G; i" C3 l: H$ c+ R

* y, x/ S1 U: C8 W% V6 @' a

---- 4. 颜色表

2 q+ h! g4 C0 O( I0 `6 S h

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

1 c2 m2 B% u2 \+ `$ [0 v

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

$ O R9 {8 J( O9 S

" P8 L( h7 x6 ~; C7 A

typedef struct tagRGBQUAD {

" a$ K3 {/ b3 P# m2 n1 Z) ]5 }

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

! \ S3 t3 c( ~% p

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

& E! g/ c2 y! x' s# }3 {

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

. ?9 i# @! |# N+ s

BYTErgbReserved;// 保留,必须为0

; `# h- P) z. a& ^

} RGBQUAD;

' c9 t' d1 z% ]) x% s A0 x

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

9 C: j5 C! w% x# P

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

, O0 X# T2 L+ l6 E, k9 f: e1 N$ T

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

+ o. I6 y! r* o; G% H M% ^

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

$ t. a! p) G( p$ R; w1 [

typedef struct tagBITMAPINFO {

1 s; u+ \5 j1 V" r1 {( i

BITMAPINFOHEADER bmiHeader; // 位图信息头

% O! M6 E* r# N& r( r: ]

RGBQUAD bmiColors[1]; // 颜色表

0 R5 s9 S& ^0 C: ]4 T# w& M

} BITMAPINFO;

# i* X# O- e: p

3 P F/ j! E4 i9 w

2 G. D1 ?! S% b: y

( r9 E0 W: l2 k) d% ?

---- 5. 位图数据

' Q$ N+ s j0 H7 l7 J

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

! _1 u5 |2 G9 I% N5 Z- o

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

9 H( q& Y$ T: s; x* U1 \

6 ^" B5 ~& E0 w; R: G: H i

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

! |* X8 w/ c4 D3 {2 ?, l; b

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

# g( n. D2 m Y$ Q& I9 ?) z

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

. i* _" t! @5 {' U& {, o/ i6 _7 H

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

, [& b. R* ^# s% G* I# {

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

6 \4 @% `1 X" ]1 F9 d/ n1 }9 f

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

' W) {3 Q: D- F v2 f; Q

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

6 f7 Q5 E$ }1 f7 Z

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

' B" {+ R) ~ g4 i" @

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

! q4 C; J6 h8 P' v" i; I

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

5 T, R3 z/ y$ n* s5 o3 [# O

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

0 J! L+ j5 m+ @' v

DataSize= DataSizePerLine* biHeight;

# @7 p3 F% k) C m' m0 ~

7 t" Q" p0 q$ t8 f G4 O

) j4 ~& k" V2 G7 u( ^0 B

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

- y: q& F- i* T. Z# A& w; D U

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

, k" `4 d: _& g3 L( B/ J, z4 w' a

) N& s; P- l* s

---- GlobalAlloc(GHND,FileLength);

" r" B. R6 w* v& @

- e& j0 ]1 ~/ [5 U) l

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

: h& V; t) a. X8 w

% k4 L6 V- J8 R8 U

---- LoadFileToMemory( mpBitsSrc,mFileName);

( p/ g. `- K3 P& O6 E9 n5 P4 R

( e ]; n( w9 ~$ `: i

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

) O% J4 z+ i5 |. L

0 D! R, L" T, _% N

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

1 k3 N. i2 U/ X2 e# U8 \9 ?

DC,

2 K* s& v$ _# k5 e) l

+ o$ }. \" `8 S% c8 ?3 b8 h" a, c# M

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

. W; h& x* ~: W3 D1 U

- L! C$ b" [8 a5 X

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

' Q/ y, A9 [* u/ O+ k. H+ M0 p u* w

1 X! r: X6 n3 x1 l

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

( O- V! e' f6 P( L

" O$ L! S% s/ _; t8 E

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

* G1 q, a: X1 n1 C. q1 Q6 }4 }+ c

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

; z& r. I# U4 f- H6 H. k

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

g8 H9 ~" {0 ~" R: h1 Y

9 ?) V- |& y9 J& d# [

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

0 E$ W( }- s3 a' B$ ^6 X* N+ I, b) y) p

" `5 f# e; Y: i1 s3 Z

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

6 `6 |# I6 f' C' ^; k. @

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

7 _+ I# c3 c! r+ W* V

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

# j9 m& w! H( [2 F2 G# s

, A( l1 `5 ~7 D: N$ I5 W

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

6 Q3 z1 R G, w8 D7 Q1 s

8 ]8 P" W* B4 c# ] S6 M) v

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

/ R0 i. q; U+ }1 i/ H* G: F$ r

- r" N5 f8 q* t% u) \) z) `

---- GlobalAlloc(GHND,FileLength);

7 i: ~7 ^/ B( L

- y7 @+ J8 A( T0 v

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

. e+ Y9 f) m r& y0 Q+ o+ Z/ L

- V6 b( v. I% O+ ~7 k

---- LoadFileToMemory( mpBitsSrc,mFileName);

/ f2 ~, m9 g/ C' ]

! Y" G7 E; t+ v1 N: b! g

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

: D% A# F1 }# |) C& P! q1 p- o! z* A

/ g) c4 w% }9 J+ `

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

6 A* C, n0 \% }! K9 X `

) E: }. Z# D, D/ }

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

% G$ N5 c$ t8 c. w

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

1 ^6 H% `) q4 [9 m' Q' a7 A

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

, d! T6 W% N" F0 m( A1 @8 Q& y

0 Q: F/ @6 B8 p' ?) s

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

, @3 U% |* M# m- l( @, K$ l0 I& W

7 R( G1 Z" J5 _1 N# }

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

8 u4 i. G" t5 A' L H

5 ?" a+ q& @6 ]. m

HDRAWDIB m_hDrawDib; // 视频函数

( l4 i" X: K' c* s2 ^6 E

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

0 g( f8 `& y9 R& i" }% c3 q: ?

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

$ x& F) W2 y% Q9 u. {

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

# c7 B3 ~4 {# j0 d7 ?3 _4 N7 r, k# r, y

# ?/ g, _3 z+ O

* F: K1 i* l& b" J

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

J6 O( }! r2 K( W' Y

---- m_hDrawDib= DrawDibOpen();

( \' ?2 q+ A; q+ z: D: I7 p

$ i2 b3 D( e$ z# v% A- F

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

& u9 T6 V; Q0 v5 Y: g8 ~5 Q5 {

Q9 l1 z9 g6 W2 y" ~! U. ~

if( m_hDrawDib != NULL)

% `5 E5 K, B% m- s2 b/ s6 P

{

5 f& s( K& g1 s( L) X

DrawDibClose( m_hDrawDib);

1 g1 A* n1 M, G4 S$ t2 H- y

m_hDrawDib = NULL;

' z6 b! ^; y7 W

}

. }# X- r0 l: ]. @+ a

/ c0 W& s9 a% Z/ o& r$ B- `. M

, \# y U6 m z4 e( t5 _

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

1 w8 e( {1 W0 ?$ b7 U7 M y2 [

voidCViewBitmap::OnPaint()

! A) O( E9 e; J$ X1 D" ~/ i; U

{

4 Y9 l, r# E1 c2 B( O+ M; w3 J7 A

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

5 b3 \" p1 t3 |; H* i7 B# y9 G

GraphicDraw( );

( c4 s9 y! A- h, [2 i2 K* F

}

- s' t0 r& U/ q1 j, z

$ C2 P+ [; ~, g" K% j

voidCViewBitmap::GraphicDraw( void )

/ q# [6 E6 _/ u! |! a6 ]

{

" V2 K' Z) b' [3 E

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

- ?! K3 t+ U$ X! [) k, ]2 f5 \

BITMAPFILEHEADER *pBitmapFileHeader;

3 d1 Y ~; E& @9 r+ {9 l

ULONG bfoffBits= 0;

\% j6 |" ~. a W" H

CPoint Wid;

# w% G5 G- @3 Y0 Y

! Y( B6 A& A U+ o

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

0 H; k; o, B" b% V2 A$ h7 K9 H" @

if( mBitmapFileType < ID_BITMAP_BMP ) return;

m. ^+ P( Q9 n" M% Q- N5 Z g

' Y6 @3 y) k7 \7 F( v! w: f& W

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

: X0 ^0 a3 |) T2 v u% @

// 准备显示真彩位图

- i0 _4 U. P5 C& Q( D2 m/ g$ o0 z5 l

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

$ e+ U9 j" n4 t, m g8 q1 h

bfoffBits= pBitmapFileHeader->bfOffBits;

+ _- F" H1 d+ l9 @

8 W5 F7 S6 U. {6 l' |/ H% p' I5 Q

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

$ r- [! U' `! A

7 c) A2 t6 m$ Q& _0 Z1 }& M# c

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

4 o; D2 D2 j, J: O. A0 N

{

5 W4 w. b0 X4 [5 b0 b

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

4 u8 Y2 R$ d( I( O3 m. g: ?

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

# t2 ]5 i2 D; Y/ n

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

6 b8 t3 e. ?$ N- ~8 S

// 建立位图

1 w0 q. k# v( [

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

# w9 ^ q: {. U; U9 d7 d

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

; i' P/ u9 A! O D$ g

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

% _% |+ p# d% Z5 G/ c) `+ ]

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

& e! \+ I, B4 u% X0 o4 Z

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

; M% k$ w1 M$ m2 d# u' r; b

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

' U; X+ f8 f2 l* a- n# U

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

3 L; B* z" W7 B' w. ?. o, r! H

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

" L9 _( s: f' v- H# z; E7 z' p' v

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

' D' d$ U& Y* |

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

4 K4 B! t# Q5 e! m2 h3 H5 }

' q5 a1 T& ^. W% F5 @* w

if( mFullViewTog == 0)

' @! W9 I2 O- [: t

{

' G8 F1 {( Z# r! i& @3 I7 B

// 显示真彩位图

3 \8 b# u5 ~. a6 ? x! w

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

$ h9 ~! h5 T+ ~) Z

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

9 C: ]9 I: c/ p2 Y8 W W

} else {

) V* o, s. l1 X' E/ O. ~/ {, h( s

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

/ u7 ?8 U( L/ z; j9 u

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

; Z/ L6 S3 x. A6 I/ f

>biHeight, SRCCOPY);

3 f7 y3 p* g+ d) p4 ]5 z U( e& j- R

}

3 s/ M3 L" Q- O! _% b

// 结束显示真彩位图

9 d$ @) E% y3 Y9 K3 P& m$ C+ a9 a

:eleteObject(SelectObject(hMemDC,hBitmapOld));

) {; \! e `# z7 ^8 _

// 删 除 位 图

. F6 t5 t/ E. ]- w8 D6 C' _

} else {

4 t4 [, T( j2 t+ i

7 {, V; M( ~1 \% ^ @7 ^

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

7 q. S. s! n$ s5 M/ q

7 t% l( j( q: G- U7 a! F

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

: e, k B! N6 N1 L

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

; `# z+ Q: H4 e4 F* B5 h

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

, P: i! ~2 _- H. ]0 q- c5 }% t

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

A/ o& W7 B, F! s+ r+ H

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

; Y( ` B' o# s& G5 |! y

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

5 w5 `* ?* A$ }

- X P% i- X9 \

// 显示真彩位图

. \' z& }+ _1 A) w8 H% V& X5 Q

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

C; }: c" B0 z r5 N {7 P5 M

7 k' B" V8 z6 |; X$ ^5 t

if( mFullViewTog == 0)

7 z0 A0 V% j, l: H. `" V

{

" A% n8 E i" I0 b

Wid.x= mDispR.Width();

% ^' q% N$ A3 G% u* w* b p5 U4 m

Wid.y= mDispR.Height();

2 D7 @& u3 a. d7 [! S0 i3 ^* N

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

; s/ Z: M, \5 j; ^

if( Wid.x > mpBitmapInfo- >biWidth )

+ C$ S" k$ t0 R: z N8 J

Wid.x = mpBitmapInfo- >biWidth;

3 c) @3 ?3 y# v% Z/ N

if( Wid.y > mpBitmapInfo- >biHeight)

0 p7 b: B& z% i. o J

Wid.y = mpBitmapInfo- >biHeight;

" G S# W& o% Z% o- u7 j& v

3 ?1 R9 S/ j* B6 c5 G) ^

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

' s8 X. c8 s$ b- g1 _0 H

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

6 x; H! x. h/ ?4 S

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

6 Q" C; M6 p O8 b3 I

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

7 b# @8 w* I7 y5 t- n0 T3 |" B) [

} else {

j# m8 \+ p0 L0 F& b) Z/ Y" w

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

' ^% G/ Q. I% B

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

`! j5 E/ T- B$ o/ ]+ {$ C

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

7 Z- b5 \ b% E6 i, ~6 L7 z

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

7 K. i" J* d; M2 G, i7 f( G

DDF_BACKGROUNDPAL);

5 K t, k3 v1 I6 [2 C3 O. x

}

& m' ?/ b3 Z5 ^ e

}

2 b( P: n1 t4 Q

return;

. Y4 q0 \& ]2 E# O9 U

}

8 ]9 G6 x+ }1 h, m- H

7 L; l! }5 m2 X5 E6 f

% S- Q1 J9 O, n4 x: U

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

3 f# Y+ r" J1 U

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

2 p6 N, g1 | N+ c+ |6 ` u& i

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

/ {8 o1 z+ m$ d

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

0 o- F ^* Z+ d5 Q8 S# y8 U. q

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

1 i, B2 e5 Z( t0 }* Z, K6 Q

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

/ `. I% B6 S. s( q# O

+ S. p. e# Q2 z

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

: P* S8 C$ R3 q# C9 e6 ? @8 p* f6 ]" r

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

! l2 Y9 a- x+ Z& f' t8 Q- ^

' \2 y9 c* B* a$ g; @% O

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

2 y7 X3 o: c, u; X$ \

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

! y3 a! R( }. n8 v

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

' }4 B$ k3 |. A4 @ P

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

; j: l$ R ^9 ?) N" b

。代码如下:

# b0 F- {3 L( C2 }3 p

5 T9 i, _ X# \0 V" K3 m

void CMainFrame::OnViewBitmap()

! E# a+ q2 H6 x

{

* E9 y! s w( }' w: J# j; p2 x

// TOD Add your command handler code here

2 g. q! Y, U8 A

CViewBitmap *pViewBitmap= NULL;

" u/ }% `3 f4 c* K# v. A! I) n

+ w% q% v$ E2 s

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

6 z3 y- C- S4 E5 O6 E

pViewBitmap- >ShowWindow( TRUE);

/ C4 c O7 |# g, o7 R

}

2 a6 X6 Q' D$ ], C3 s

! j; U. H; g. I# p, ~1 J

" c4 ?, F: V) z O3 F

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

2 W& `, c) |5 z& m) k1 {- E0 |

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

3 N+ v+ P6 I; U- \6 c

2 k4 @0 o% t" K, |8 U! m, _" |

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

) K* S) b E3 h0 h

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

! {1 m( M/ ^' t: u$ n* v

! \! s, T, Y7 d8 e+ x4 i

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

! e4 H( n% S6 p$ U9 h9 B

5 I" Z- P8 l8 {& b

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

( }% D7 i9 ?+ ^/ ^, h, Z! M

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

2 d- V# V/ r& n3 J5 }7 S# j4 `

: t2 Y* O# Z% m

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

) C; \6 T/ M! `

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

1 S, T; T+ p a4 U) i

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

. y: u( U6 U2 _1 P% x+ N1 i

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

- b& O! ^' f1 @

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

" M; W4 W' y8 @; j; S7 x

8 g/ ]- j2 A7 L5 g% B% J$ Y, |9 Z8 G

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

! q, d8 V. |5 ?3 v0 q7 {& {

就可以显示该位图。

$ e8 B' U8 c6 o

) n/ }* @. J# z3 H( f5 q

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

* X" N. L, A7 g. `! d ' e6 c) i6 }6 m) c

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

! ]* }3 E5 u0 G% R6 }4 y

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

5 F8 n# F7 v- \3 h$ d0 |2 i

真小,显示速度快。

( @' a/ w t- K$ h2 y' U

8 w6 A+ `8 L) W+ u3 S% t

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

1 ^0 x' \0 M2 A5 m& d

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

) m( _/ J$ J/ F8 A

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

) K% f0 a9 z1 x/ k, R/ v9 f

" P S% R8 ~% m ~8 K( v: f

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

8 z y" L+ ~4 ~$ m

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

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 17:51 , Processed in 0.460077 second(s), 52 queries .

回顶部