QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

: [/ n7 I( b; ~

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

4 ~0 ~* Y* x2 }7 w$ n3 ]

张义云

$ J; Q g" z# s' ?

' } |9 z0 u, b2 q2 M

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

% M0 J9 w( m' {" x! T/ ~

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

; [7 k# g" v( A. Q' s

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

& _4 [9 [7 a9 @4 {. I; ~6 a

. i2 g: }8 h& H% y6 m4 g- c- Q7 ?( v

---- 一、BMP文件结构

3 f) ?9 k+ }! N

3 h0 }% U$ q# E* D6 y; I

---- 1. BMP文件组成

: F0 c9 g) `+ m6 y J6 r

6 Y& i/ T4 i7 T. @2 [

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

! I% n+ m0 v4 s' N4 s' C {

3 K4 A- w# H; h4 U F

---- 2. BMP文件头

% }! c6 E( V6 R9 @6 N6 c$ s+ K" H' @

9 I. j0 ]9 `5 i5 ?# g7 ]

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

* p1 {0 W2 q' F- i( E8 ^/ x" _& A7 {

6 v; r5 o1 N% O# q

( V+ V' B5 f' w+ C& N2 |9 i

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

' [$ v( @* D$ z

& L2 g7 S, } h

typedef struct tagBITMAPFILEHEADER

- |) e" k+ ^% W _

{

5 ]; @5 }; C' x3 p( I& T2 Y4 ]' t

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

" Z$ V' m) e1 w4 P1 b5 J

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

+ B6 B$ V" Z( [9 s/ @1 r

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

/ \# T$ {: Y' ~

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

( n9 v; v5 N/ [: c: a

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

( F7 x4 d* u2 j6 ]: h

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

2 `0 P3 c+ Y# I- z, M) f

} BITMAPFILEHEADER;

! p, C; S* G0 [% s/ q& i' X2 j

G* W5 w$ |: _

8 R( V2 O$ P7 J: e. |, ]$ J3 A

---- 3. 位图信息头

/ I) ` @* q' ^' x: ?* F Y; Y- |

----

& a9 }. g, _; R+ R6 w# t6 Z. S- V

, f+ y9 d' i+ S2 M+ j/ K# D. i

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

" m+ a' l7 q* T( q+ Z! _

typedef struct tagBITMAPINFOHEADER{

- y% ^% Q& i0 p& O

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

; p, a' D% ]" t) x. j

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

; I, K$ `) h; {

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

7 g# G* L1 b7 M0 V

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

$ s" s& a+ g U8 d# E! \/ ~

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

* u3 i: N1 G' {

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

( H* V9 E# R; ~& H

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

8 ]. e0 n0 _# [

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

! y$ `9 P: J, N3 E& x

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

( r! A4 A1 q* ^! _. {. P

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

& I- _' Y" S' p# H

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

3 P8 s$ L* k) E; E+ Q

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

: [1 [( V: q1 ?, K

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

. D1 e2 {: \: c5 j2 Z1 N* K! i

} BITMAPINFOHEADER;

0 f) f* Q( O/ @' ? [

4 x- g0 j! Y' y( E0 n! o

! C' m1 [ E* O) V s

---- 4. 颜色表

: l6 {# e+ j/ t* C$ R

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

* Y% N, o% A9 U1 N' N* A

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

7 {8 U; `6 K: U! s

2 p: a- D5 B* ?" W( f

typedef struct tagRGBQUAD {

; h+ s: X6 {% S

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

0 `4 c, M. G+ S" V8 ~' B

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

0 P- y; a W! h% J% m

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

1 r; Q0 p' N! O

BYTErgbReserved;// 保留,必须为0

2 N; x+ P; W: s6 M) x+ M; ?! C1 Y

} RGBQUAD;

0 E* w; j8 i7 o H* J

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

; Q2 J: Q7 t# m7 z

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

# Q5 s# |- _8 i

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

, a# n2 @& \( ~( V2 Q

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

% @. [7 Q9 p" D

typedef struct tagBITMAPINFO {

; _4 X' c" L3 E+ `) [

BITMAPINFOHEADER bmiHeader; // 位图信息头

! c7 h' q" s2 H4 c) ]0 i

RGBQUAD bmiColors[1]; // 颜色表

4 o: ]. q/ X: r w, J- ~

} BITMAPINFO;

0 W- k- b+ H5 J4 h# T, Y0 M

$ T% k: ~# T' ^+ w1 l. B2 C7 T; }2 {

' G5 p& \: r7 ]3 M) |

1 C1 L% U' Y% U5 f* G2 t+ j

---- 5. 位图数据

9 F' t# r0 ~- |: [

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

. N/ p: i0 m( v, B9 b

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

' C! B) n% u3 j" ~3 q

% h+ x8 T0 z4 }9 J! Z2 G6 m& ?. p

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

: e7 D/ L; S) u: g# i5 ?

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

' N/ y3 g- M' d W

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

8 g) k4 g2 y4 g8 M

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

9 R* g4 h6 Z( m5 |- \7 ~

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

; c$ R% L1 j2 e

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

0 e! y- [' c9 b& i( w! b

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

- _( q- D* G. [( J; s$ p$ Z$ N+ Y4 z, \

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

7 o1 f1 P% V6 O% r$ |

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

$ [' x& x. ^9 n- O4 Y7 L

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

5 x5 m. j8 w8 n

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

1 l% I! }) `; B0 _, M1 [0 l/ ^

DataSize= DataSizePerLine* biHeight;

# w$ V& D7 Y& L/ w& t

2 a8 X$ w, R' X! j6 Z; \+ \5 Y# ~5 z& p

7 k E8 q, W( G# Y, ~, t

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

. C! e) t# z+ J/ o" l& a

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

5 d: b' @- f7 Y& ?

8 p* L3 x8 u( K& f8 |6 S6 f

---- GlobalAlloc(GHND,FileLength);

( b0 l: {. G! w4 Y3 U# o# ]

5 t* d4 N# Z' H0 A m" P3 R

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

7 L1 u7 L! i; e; [6 {: P4 X8 F) `

, a( c( b/ p$ c; N

---- LoadFileToMemory( mpBitsSrc,mFileName);

( V/ _' Z1 x! ], Y: d) b4 d1 D

2 A1 s7 |1 r8 s( M. g2 ]- n0 l

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

0 G: n: u! z/ R3 O" x$ ]( Z( N6 e

/ ~4 D. P1 W3 \7 ^

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

# }; P2 s, x* _

DC,

& F$ q+ F6 M1 _3 f3 v/ F# w: ]! o! H

5 h% Y" n1 }; X* A! q5 s$ k& W

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

2 c! \- k9 I4 o$ Z8 W* h8 h

. i: R0 Q6 e6 b4 j* w( N5 P

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

0 Q8 U1 Y V8 ] l) Y: C* @

& L0 s3 Y7 W7 [% ]1 m* m( ^. {" H/ j

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

! }7 ~ I+ D/ Y& O

& [5 `5 k. }2 w5 z7 g$ G

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

0 \+ ]8 M6 k: S4 ^0 D; b

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

$ L$ l7 W' s1 j: u7 n. q: s5 |

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

# m( Z5 L3 @3 \3 }6 }. E

, |1 D! n7 P0 ] {" Z3 p3 T

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

$ B2 _* X. p6 T

7 c0 B/ g2 j$ ^, m8 [

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

! T9 R6 t' j) Z

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

- Y; n! h6 l' `( w# V7 X

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

6 U6 R+ |1 h: d8 ?$ c- q

% a8 a6 S5 X' i, L0 y

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

+ k/ F V& k7 s& n1 h; O

" a: R$ x: E) |: c+ a# {

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

& U. J* Q7 Y! g5 h- j, g

; M- j- t$ D7 q8 j

---- GlobalAlloc(GHND,FileLength);

! t: I3 P! @- q; ?; `8 e& w4 e

8 s+ l' o8 W' m: r; t% y

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

* Y6 K) v* C" w1 K9 l, p

' ]8 P; R4 h! N+ G

---- LoadFileToMemory( mpBitsSrc,mFileName);

2 r( q. r! K+ C, |- ^' ~

# k. Z) B# _& E

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

3 L& W& `$ A, p( z# A$ P

* [# W; M q+ Y

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

' l* s9 b; K1 Z' {! f9 s

6 N% O" Y+ I! a3 V' u

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

- K x; ~7 Y' Z3 S% u+ x

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

( _- Y$ N1 ~( x/ f4 k

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

& a }8 m( \6 \9 j' [

! t1 `: r$ A4 Z+ T: Z5 V

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

Q* T8 X3 W7 b6 |" i' @' J

2 \9 ?8 b0 a; w# r$ G5 o

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

2 f$ p7 {& _( s4 Y8 D3 N

, U- J# f7 _2 U' X- C

HDRAWDIB m_hDrawDib; // 视频函数

: E: V7 F7 {2 g5 K2 R. o% T+ e. N

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

- S, A' G- z+ C$ F+ t& h8 R5 e0 B

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

( F0 @ p0 @" x+ W# v

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

" I; D/ z! ~/ ~- N( y. W9 ]" M

; f" T- Q. I i& P7 Y

; d0 ], _$ d5 j

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

6 \6 ?% B- Z# J0 Z& T

---- m_hDrawDib= DrawDibOpen();

7 @. K/ C" E% |. ^+ |

6 s8 |* G6 _* d+ r/ J, ?; D5 j7 Q

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

; S1 ?5 V; k6 ? S; t3 a) A5 V

- h# \" z9 Y( m- _, I

if( m_hDrawDib != NULL)

4 Y- l" p5 ?! y" n9 Q

{

% U+ z/ L0 S! ^

DrawDibClose( m_hDrawDib);

8 i0 x/ Y" R6 c6 @) }8 v

m_hDrawDib = NULL;

9 K. {; D% `1 J0 F7 y

}

3 a, t5 G# l' b# [

- L8 @) ^% {( L) o2 O: P

O* s2 o5 a8 Z& K- \- ] i

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

h3 d+ \* ~; t1 A& j6 P

voidCViewBitmap::OnPaint()

5 ~ ^+ ~) N6 V) q2 e* G& I

{

+ V/ B3 a7 G( w

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

6 L* ^0 q! i3 ~; c) f4 V% t

GraphicDraw( );

/ ]4 [6 ~# y0 ~/ ~' s# k

}

V5 a( D4 Q3 i" G6 S- C. M# d

* o0 |, z2 ]! @1 Q2 I$ x( \

voidCViewBitmap::GraphicDraw( void )

7 |+ e- K2 n) r+ ]

{

/ ?) B1 K& ]4 V5 y7 p/ D6 p* q

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

/ f, E1 s; }+ d

BITMAPFILEHEADER *pBitmapFileHeader;

% J' |: B( }: u5 U

ULONG bfoffBits= 0;

" \6 {6 ?4 D" Z: q1 ?) }- ^

CPoint Wid;

4 B9 A2 ^; @! z7 [7 b+ Y

, v* V( N7 |1 i7 I# X+ m5 I7 }( Q, `

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

9 q5 H; P+ E" s) ?% q8 Y

if( mBitmapFileType < ID_BITMAP_BMP ) return;

7 x4 b/ ]4 R" [! X

4 x5 K& k$ J* W$ c( v& m; I& m3 z

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

; ^: k2 Q7 O: T5 F$ g

// 准备显示真彩位图

8 {5 J0 l2 l* n$ c! L+ l3 u0 \

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

g/ S$ E! \: _8 [

bfoffBits= pBitmapFileHeader->bfOffBits;

: s. R$ G+ G* S; }. r

$ j2 W9 n' N$ P" Q% k

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

! K: u( \0 ]/ f

. |! u$ W# F5 t' K

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

# N5 U5 @* V/ z# z! {. R% }

{

4 }9 s1 F1 \( X# D0 p" u4 ~

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

- L+ Y0 \. O: E. z

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

+ T9 a+ ` p$ m: n9 `- v

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

! s' P/ [- L$ X5 V

// 建立位图

2 |3 j% d7 D- H* `8 D( Z

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

9 d: k+ ?' B) ?7 x

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

+ U" X) a4 K) _( o! w2 t7 q z4 R

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

& ~; f( j! @% R

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

# z2 v0 a4 \, M

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

" b% Z0 E6 k; g3 ]& A

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

0 j9 |/ q% R) l' ^! e

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

) g; J4 H* u2 |6 V3 x

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

; }. k$ u+ Y4 b& R+ L( m5 K

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

1 P3 V' @ a4 X# F" g0 L

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

8 o/ g A* Q1 y8 U

M& v4 w* j2 P

if( mFullViewTog == 0)

9 K& U0 f7 |" O) ?8 X' \$ T

{

2 u( {0 O- U5 m: a8 {6 ^

// 显示真彩位图

5 }1 D* X& s" b

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

, Y! x" p) ]8 {% y

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

" I+ G; w- N, I3 P m( T. l

} else {

1 |0 O- K0 ^) f0 r3 [' s4 `

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

! H- s# L8 ?' D$ b7 X" ^" w

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

$ u* v, [! @4 {4 g( e

>biHeight, SRCCOPY);

& m' \8 u/ H9 I$ q

}

! a/ }, s7 M8 d: E

// 结束显示真彩位图

; M ?: c: o1 U4 a8 t" A8 m0 V8 B

:eleteObject(SelectObject(hMemDC,hBitmapOld));

, Z1 {" _! K) f4 ]: P) U

// 删 除 位 图

$ [: i. P7 }4 s

} else {

3 }3 a2 t" d& F6 P( ^! S

/ i% X; c& i& r' ?

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

. Z5 ]4 K3 D! i' C7 V, X

+ Q2 \* F6 ?: ?7 ^5 S

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

8 Q& X6 K4 Z: a: {7 k6 \+ o% g

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

/ k' h8 {& D$ [) p, ?2 x. W

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

, Y' y& c8 Q( V/ @* Z; O8 q% o

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

+ N( _4 U0 `8 F5 R6 r

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

& F( h+ K+ ~, B7 z' `

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

# J8 o* w q2 A8 c. ] u+ \

5 Q) D9 ?- J( r0 J3 P! Z& I

// 显示真彩位图

8 d' A; s7 I4 v! \+ o, H

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

5 a; Z5 O/ [& y# E. L2 z

* V( k6 z0 P5 c& J5 K+ A. ]" V

if( mFullViewTog == 0)

0 v3 L# j* Z9 d" i% Y( V @

{

2 r6 f$ a. ? |3 M6 N9 B7 C

Wid.x= mDispR.Width();

! ^9 z! D, |2 v+ s# s, p4 V9 m

Wid.y= mDispR.Height();

" ?9 ~8 |6 ?7 k$ Y% {9 F( N5 g

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

6 X- ^) ^# j2 s; }$ ~

if( Wid.x > mpBitmapInfo- >biWidth )

' y5 K% g. \ R: ^8 l

Wid.x = mpBitmapInfo- >biWidth;

8 ^6 X! [/ \1 D0 [* |

if( Wid.y > mpBitmapInfo- >biHeight)

4 @1 Y3 P6 Y# @; D

Wid.y = mpBitmapInfo- >biHeight;

9 R+ H0 t! s* N9 C, Q" E2 |

' J/ z8 T5 ^* I3 c. x' U

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

0 T2 R' _ x! j/ g: c: T$ m

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

9 K7 C9 A! f, ` ^. B

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

`9 R, b* _: E5 G+ ?- e

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

J/ P1 ~: ?; W: I4 R

} else {

1 V. m- i4 c5 W

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

3 @; w9 s+ i B

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

4 c. ^: |( L. x/ o5 V9 s, D& H7 ?

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

0 Q; U+ i% I3 v) Q" h r- L# Y; C

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

# M5 s' ^7 _7 I, `

DDF_BACKGROUNDPAL);

* V$ _6 _3 l& G7 X

}

7 }7 S9 c7 L. [: {

}

, {8 M" V. c- K

return;

$ j: i5 p) M! O4 \/ k

}

l8 B, s0 R% r

6 L d: _( U* g) @8 B! z) a) ]

7 q0 }8 W3 l$ c* Z/ o$ ^

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

- x9 Z' ^5 W. M4 g7 \: @

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

, x1 o" p2 b! I* K; V! G# O

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

! } y$ q4 \ J2 G' b

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

- d9 o% O1 C6 n* ?/ Q5 P5 V9 B u

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

' @( s: v, e/ f1 D B. c

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

4 l! z0 n& Q. C9 t+ k) a

: u' ?0 O3 X- A1 s# m

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

* o6 i, J: y( i$ s

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

! [$ i3 {7 M# i5 h9 O+ K

" O% E0 A. C$ [. o3 M: U3 X

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

j7 b- E; j! f8 T

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

0 r+ Y& ]. ^. O+ j1 s! h

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

0 h4 W( S' i, i* M

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

2 I; k3 u1 j4 p3 Q* J1 c( j" g

。代码如下:

. i1 {1 k& c( Q* G$ o

! D! ?0 i6 ]/ _- D5 H; d: x

void CMainFrame::OnViewBitmap()

3 S6 p* i& {2 `6 K5 L3 |

{

2 v$ l8 d1 q) m

// TOD Add your command handler code here

$ c6 v& L/ y! d/ j, x9 N

CViewBitmap *pViewBitmap= NULL;

8 O7 u4 t5 p- N

2 [, ]: N: ^1 W8 n0 p

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

( t% N3 S& X% Q: y

pViewBitmap- >ShowWindow( TRUE);

n* r/ t! D- t, M, l

}

, A" o' q; y7 f) w5 ~

w5 C' |- O# h d' \6 V

, y- a( E% \+ C/ K" T) }

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

- g5 S% W- ?1 V, g8 i( t+ d

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

3 F R* p& _2 ?

& ~! E- a; O3 z! U" D: c

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

7 T- S% D: S, o4 k9 ?' I- U) [

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

9 ^) Z9 N2 p8 d" _/ s3 e4 E

, y; W. x' [3 s9 f1 B& O

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

- J5 `7 h8 M8 O1 w3 U# B

& R! o' D/ k" K2 [1 U# a! \

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

; V$ K8 W# c3 b) r# Q

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

& d( j4 f2 D: O+ a/ o( }

; J7 Z- y5 q5 H5 z8 R

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

( O U! H2 @9 h" E$ h l; W

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

7 |$ B" v- R/ R# d8 O

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

; T* N; T1 I, G" \0 T% J% b

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

( R6 J- a6 c2 B$ S* n

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

- a) H7 |8 o" S$ z& U) f

# w- y# a1 t$ k. @$ K3 [8 W' E

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

/ u. H' [: P7 W6 y9 S2 U

就可以显示该位图。

9 r; V. @4 k( p

) w* U7 j @& _

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

7 @0 F! L/ e; x2 s* e + T0 D' j8 h4 p L0 |! E

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

+ o% i# @' }$ P) l

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

6 C6 i1 Y" ]. j, |/ k9 L7 q5 O

真小,显示速度快。

( _3 A# t& o2 F% C! I$ ? P! i$ V' F

. J! j4 V1 m |

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

" W5 }7 a o; f* ~

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

' w. S1 H5 j* `9 z

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

. m4 H, \& U( x% ^8 w# P

, X0 k3 H' F# T

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

4 k- y% W% a4 a* }; ~: _7 l* E* d

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

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-10 23:38 , Processed in 0.398311 second(s), 51 queries .

回顶部