QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

+ x" n/ f+ m' K

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

' L' _- X8 B) J4 U

张义云

1 z3 D! N/ w$ |' X

& }! x5 X+ ?& N0 G; n

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

7 @, \% @0 D+ D6 Y

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

+ y1 N! Z/ z7 y8 t! n: }

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

$ ~4 A3 P8 R/ X6 z6 |

8 e1 w' J% z/ X& M

---- 一、BMP文件结构

$ q: y8 M; d! n$ R5 ^

8 O K2 e7 W6 H7 l( E9 R

---- 1. BMP文件组成

6 T$ k6 V. U4 c+ ]

# P* T& ^' K# u; J

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

3 G2 P9 G6 f2 S" r3 \. I7 V

: i f7 t' S8 c7 }6 ?; t3 y

---- 2. BMP文件头

+ u9 z' Y, G' M- Z! O0 Z5 O$ y1 O

/ K8 a- G. A, f0 r

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

* _9 ?5 _3 `9 ~- e) D

7 l: v7 ]- D6 D' H- L+ ?

" F& b+ ~. ?" E- O. u# p, ^

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

/ ]* `6 `3 h# F" W6 x5 u+ X7 B

0 [4 i* b4 h5 {

typedef struct tagBITMAPFILEHEADER

. k2 W; ^0 J) ^

{

+ Y: }7 ]* M) ]; S2 [2 L. ?$ {- V

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

- _/ {" J, }, |4 d/ u

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

E3 |) U& A5 g E5 r+ T: s1 |# Z2 g( X. a

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

" q, Y( q% c3 B- p1 D# M

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

/ G7 H) A0 p( a

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

' s1 [3 s7 W7 B; o! i# p* `- }. K

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

1 Q- P: I- v9 l, C- `. O

} BITMAPFILEHEADER;

/ N4 E M7 o6 j

5 h, R1 M7 H1 a! x

+ W; i9 {. u Y# L, y

---- 3. 位图信息头

# F4 q0 @, W2 X- v `! b% @

----

( d% B0 b( s3 B2 t C. v( i

1 q* N- O8 v, R' c4 U0 f

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

. B7 d+ A6 I4 O: z* m& Y. p

typedef struct tagBITMAPINFOHEADER{

! H$ k# V3 F* g' a

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

2 z4 k' J9 `( l# T9 z4 R

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

4 A" g5 o! W% A5 p3 i% R

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

. X8 ^5 v' q0 R/ u- K z7 @0 g+ ~

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

( I- l3 {& i0 Y7 M9 \

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

* S) c1 s p8 I4 S. J4 e

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

) ], y) H; N3 v4 i- C; x* U

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

8 n, [+ Q, F; E8 ?: ^# b+ A

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

% H5 t3 B% }- N3 K; q# D

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

4 t; o4 X* U$ M I( L! H

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

8 w+ E) a( W. F" ^& _

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

n X# Z7 B ]: x0 U) D

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

6 O+ z& B C( m& b& r

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

- t4 x$ L+ L+ A- \

} BITMAPINFOHEADER;

* K" k4 l, D! D* d' G3 w+ S! \

. ]* j( M3 R+ p. p3 N+ L

: f: R# r5 @0 z3 X$ I' v

---- 4. 颜色表

5 k7 k+ J/ g* J3 E- r$ W

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

' Q( W" ]; r* o, k, u. k

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

8 R3 ?) J$ L+ y& F' _

4 h0 X2 Y: G2 E$ r- B

typedef struct tagRGBQUAD {

2 r( W, E7 T$ ?$ {1 T4 Q3 f" H7 Y

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

) v- \1 K8 _; i e

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

5 i# \6 K8 M" A3 @- _, z: n

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

8 a5 A" X% g5 L8 `3 V

BYTErgbReserved;// 保留,必须为0

. _+ O& h6 n2 E

} RGBQUAD;

$ Q& ^$ j: ?% {$ ^7 i% x

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

2 ?- x/ b1 y t5 c: Q- `! j0 f

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

8 S1 M/ ^7 W' g6 S, ~. J' b( b

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

8 B7 f5 m1 z- h7 z6 |- G

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

5 {: @. B+ B# d$ K- X; @1 h

typedef struct tagBITMAPINFO {

* a8 l& C5 ]9 L: J5 h' s

BITMAPINFOHEADER bmiHeader; // 位图信息头

1 [0 u2 R8 n5 s4 B

RGBQUAD bmiColors[1]; // 颜色表

Y4 s1 n( Q2 F$ Q V/ O' O

} BITMAPINFO;

% T: N3 S$ Q; y X

2 ^5 s+ q% r7 M5 Y2 c

6 n- u9 l( B7 O& b

3 d2 z+ t8 c: c( m+ O

---- 5. 位图数据

@& H3 Q- o5 o/ r: p) {6 Q% m; d

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

# }0 ?/ D. g$ ^/ F. u# \

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

% Y& |% M1 r6 h" H: M0 i' z8 g

" Y! G/ i! ]# R( ]- d

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

6 P" ~( g- {( @% a7 M' P% z

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

( V# D# p' S/ t/ J9 h( ^

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

( a! j& M$ q3 S9 ]$ x* E; W

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

1 c6 t2 \( X+ y+ g

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

+ H! Y6 i. O& K; h- e: q8 ?: I

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

, f5 F* U i, x( s. H9 E7 Z

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

+ [' l: @: V |! h2 {

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

( o6 }5 f4 H; t: r/ c, W( M

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

4 p$ C# Q8 Q9 Q

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

. v" y' j7 e" j& K- L0 R4 Q

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

) c% @! u; X2 }% J! R: ]

DataSize= DataSizePerLine* biHeight;

' W/ b8 g1 z. V2 q# o) \ V

2 L* g# }- f0 u' U ^

a% d; k; q8 G7 B* @( Y

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

; Y) H/ J2 e+ m) E. P2 @

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

9 U: j5 D( ^3 G' b' T5 K0 n& O: F4 j

, v9 M2 r- |& U/ y! A0 [3 ?6 q

---- GlobalAlloc(GHND,FileLength);

- X: w4 _4 O" g. R/ V

+ Z0 q8 J- j2 i8 C# n

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

0 V% X5 v, s6 W4 s2 \+ y

" H: |7 X2 L |% Z* x8 {

---- LoadFileToMemory( mpBitsSrc,mFileName);

0 z! p- Z3 y+ H! V

- B2 |2 y! C( ^& {6 N9 d, @

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

$ V0 W3 i- \8 r& I+ S8 c: g4 D

+ G( ?4 B* e; J0 l* i

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

# I& q" a" r5 X; o) \

DC,

7 f- Z8 B. d; z6 K& L

. c* O( @- p' ~4 f" ?) N

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

; H) V2 U# @/ N2 b

$ {1 K5 T3 n$ f) W

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

" Z; ?6 `# _* H- u

3 t- j2 s0 K+ E; p+ h

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

2 r6 Y' S' l/ O5 S

; N1 V/ h6 [# S* `( M6 s! U+ X/ z

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

7 K' R- Y: }2 q

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

& i; J; B: C# O( D) K

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

0 }. S! s$ h x9 Q

$ n/ O8 G5 \+ R

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

8 I* J3 T4 H, i( ^! x

! [- Z: z+ D* A/ g$ V

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

' j$ k) V& C% Q c6 O2 Z

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

2 z- }2 V9 b/ b, v3 Q; b

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

0 @# V$ `5 o+ F# y1 i

$ M% T3 u. r; y2 T5 v& d+ \ S

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

( E& T+ d: P0 |% b$ N1 Y7 d

# H0 z/ W: W; f8 W1 k7 {+ c" h8 r Y

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

5 _( ?2 I8 Z* O7 e4 G3 E4 ~

; Q$ B' Y+ q: c- C" t4 ]* l$ Q0 O

---- GlobalAlloc(GHND,FileLength);

- }0 r' u. _5 V4 y

# d7 h, B$ c/ U8 B

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

/ ~6 X" c& E3 A6 b2 D

, J$ U8 }! n% T

---- LoadFileToMemory( mpBitsSrc,mFileName);

& K0 _4 j7 U& J6 m

+ `3 X: c; n/ f8 N; p6 m; |$ L6 q# t

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

- W5 f4 e2 Q/ _; p2 p" K

8 B% p& @7 B- M8 ?5 f! g

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

$ ^5 b% G2 V4 y" e/ k, O

' d+ E) _8 ?% x' Q, I

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

0 r# I" h% V) J4 w0 Q6 Z3 o

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

_+ M6 Z+ P2 F

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

2 B. i% O3 V% [2 J$ R5 r5 p; v

: I- [, S3 Z: z

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

( G) x' L3 F2 \: T) m; D

! B1 N& F5 @0 z' o) |

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

* N& |5 a! e) C' j8 ~

2 w9 B; V8 n. y8 C, L# _

HDRAWDIB m_hDrawDib; // 视频函数

; }. Q, E2 G4 V: X( X) Q

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

! S S: R% ~4 {3 [

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

1 |* S/ F# N) X5 y

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

" ^3 Z" w8 Y* e9 K) Q! M) o& q

$ p' C% X5 q' u4 G

! ]2 W; R9 n' z

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

2 [/ H% Z" ]4 {$ k; g3 N

---- m_hDrawDib= DrawDibOpen();

0 X4 s7 a' i4 h

W5 v# M4 z( s6 \5 q) i

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

3 G; g) n# y2 U5 X+ ^$ M8 h

3 R& l- T ?" \& z4 p% S* C; U

if( m_hDrawDib != NULL)

; e+ g2 ~: s8 a% E" R9 G

{

' i d" }9 D" V' }; D# v" u

DrawDibClose( m_hDrawDib);

; l' a0 @3 q/ Q! {8 t

m_hDrawDib = NULL;

+ I8 W( o5 e5 s+ I6 {# y

}

. o3 X; [& [! Y q; S4 s

. X; N1 K3 t* s1 |$ b, P

. N/ z. y e1 x/ \( P

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

5 g4 w+ W' V0 J/ i; O; ^

voidCViewBitmap::OnPaint()

2 |/ y( w8 c, A6 p% J% V+ i2 c

{

5 t: _1 w8 n1 z& f0 K

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

' p+ q) B. o D2 U# v: D% ~

GraphicDraw( );

. W, {& b2 C8 F" I% B2 V8 k# x' w& e

}

! W$ J, P3 p! o& M. C4 H( f, D

0 a( ?" a, h# o% P( f. t

voidCViewBitmap::GraphicDraw( void )

0 X3 V0 U- P6 z

{

Z i6 x5 s. f% W. Z# [. O

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

. O0 }3 N8 k1 w+ i

BITMAPFILEHEADER *pBitmapFileHeader;

% u- w6 m1 s& |+ z2 g8 H O8 {

ULONG bfoffBits= 0;

8 H( d6 Z' C n: E0 D! c

CPoint Wid;

! U" r/ v3 k" q2 W. U

+ f5 L: a, n- s

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

8 r9 n+ Z7 g5 U/ t y- u

if( mBitmapFileType < ID_BITMAP_BMP ) return;

9 ?& m. H+ ^$ ? z) j6 A4 J% l

, Q/ f* t0 H, z1 D6 z

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

0 n% O( d+ x. ~1 p/ d) B! M! J

// 准备显示真彩位图

, p8 S u2 c) P) u, Y6 @, T1 `9 _& ?

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

) x2 s4 y* ~4 p; ?; E6 D

bfoffBits= pBitmapFileHeader->bfOffBits;

3 z. | t( D* S6 f5 H

+ g$ _6 h8 P5 d" Y% q2 r0 O

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

* P# p7 ^/ e, P8 G4 Q, I

: I3 f, c: q! r$ O/ y7 j8 A

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

. C. V- z* O5 u/ A' X! I

{

% \6 i+ e% m4 b0 W2 ~2 v

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

9 Z. b1 S- X3 Y4 a* [ E

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

5 R& d& p* J1 N9 t4 g6 N

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

: d% z; t+ U# ^) Y. B

// 建立位图

8 s3 H. c% K2 J0 F: L& Z, e9 W

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

3 u5 m2 k3 i( s/ o4 `; n3 E

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

0 H) J3 Z% B/ f* |: m4 `

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

/ n& u! C) }. C/ x4 u x! y

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

" S! p8 \+ }7 V4 k% X! X

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

H# {, v9 K/ q/ Y

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

* E( Y0 Z- R; r( d( }

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

+ _, ?7 e/ N/ g- u" W |/ C

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

r! r7 d1 `/ a

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

. j- E q( j4 p( @$ ~; x2 |/ l

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

, Y$ l# |4 H: G8 ~

5 h8 y+ a& l8 B) H( y

if( mFullViewTog == 0)

, R# K H2 f& {8 E+ i) c

{

/ \2 W F' |4 {! @9 P! J

// 显示真彩位图

9 Z4 M0 Y& q2 B) p: {: A9 y

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

% j8 [! X, s0 u" V

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

0 P5 a, B1 A$ o

} else {

~7 ~8 o" F' P% [ ~4 W

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

6 r/ e( a; X+ ^( b+ t

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

( X% k5 s' S( W6 x% ?% b5 a* r

>biHeight, SRCCOPY);

$ C* d* E( s& u

}

8 W/ g- q4 D% ?" k) c

// 结束显示真彩位图

7 j8 }, r: b' j4 |) A# O: e; \

:eleteObject(SelectObject(hMemDC,hBitmapOld));

6 z2 q# }4 v$ r' ^" ^# D& I

// 删 除 位 图

1 j' v d" i% _5 v. M7 h

} else {

9 \9 j' B. [& ?# F8 \; s# j

: C# K& e6 b$ w2 [3 `! k

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

) j. I0 {2 p2 A3 [

$ I/ a5 i& z* f" |) {

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

6 h+ {. d- M, h

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

( ^. F4 b# V( R" }# n& ] O

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

& T2 O& f2 U$ ^% o& Q

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

# |" x+ p6 Q9 @8 p

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

& x# d% h+ T$ V

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

+ f2 S7 @8 V( _

: z9 S$ E- r' B, Q' e. t$ h

// 显示真彩位图

! r, l9 `/ c8 a

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

! |( g6 ?! e) u) t

8 C D6 q ^& t

if( mFullViewTog == 0)

( x% I! B% k# l5 J. g

{

# N: D# b* ^% Y+ e

Wid.x= mDispR.Width();

, ]5 X. K8 z; m& W: |4 \

Wid.y= mDispR.Height();

# q8 N( e. x" N

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

1 r! x/ A8 m' ]1 g. s

if( Wid.x > mpBitmapInfo- >biWidth )

+ P) S9 I3 k+ g0 ^

Wid.x = mpBitmapInfo- >biWidth;

( f- u! e) H# G# q* _7 L

if( Wid.y > mpBitmapInfo- >biHeight)

3 o) N; N- K" n5 I1 \5 V% r

Wid.y = mpBitmapInfo- >biHeight;

# i D4 g8 p6 |6 [0 w

4 m) e2 o. I3 G

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

" Q. N M0 o, A/ E) j& E3 J7 u

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

! ^! x" @% Z6 R( U3 I0 M* M5 W- c

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

( k' v1 r; G/ ~( k5 z% G( m- s

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

; s. P' n2 _3 I( h0 `

} else {

i1 y) b& x. z9 l- u: u

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

2 R0 T# T* \: ^

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

! ?' U% x: ~! z8 S% V( ]% G6 U' s

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

- ^ }* I0 q5 @2 K& L# R

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

/ l9 |2 S6 D- {! ]# Z; U; u7 q

DDF_BACKGROUNDPAL);

4 @: {; L, A B* Q: r8 z3 P

}

- m/ i; a* m) ]9 g: L# n

}

3 e3 }5 U6 l' M

return;

0 J; f, j8 c6 w% \* Z) X

}

0 h7 K! B' B% B

( I) y: }5 Z1 a+ v" p9 s5 o" W+ c7 f- x$ c

& h3 J3 s2 t9 |6 Y7 k& o9 N$ G/ c/ T

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

2 G# u) K# d5 J0 c& l

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

0 U0 r1 ~+ I6 l+ ~$ l; |# j. a

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

9 n6 R' ?0 V6 u g8 ?: }% L

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

5 s; W) W- h6 i

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

( O; D" D3 x4 n; ]. V1 w" J

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

" |; f: m, Y- c/ i$ l% f2 g

: S3 _. x: E5 u! ?

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

2 ?4 j+ F, U3 `, P- o$ t( }; ] H

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

7 }! j( ~) j: P: s

/ b) e- M+ } g. h) K

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

$ N! M \, v; V+ {. a

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

6 O' z. H- q* f1 f) @. k1 ?/ W

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

# i4 z# C. G7 J

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

t- i9 g X! H; J) N. ^. l

。代码如下:

# r( X" q+ l; {1 F

' h$ X# x7 V( H' e

void CMainFrame::OnViewBitmap()

" u7 ^/ c5 o" G; S

{

; E% D! z1 a: _0 [& h1 f# @ _

// TOD Add your command handler code here

# s5 U i* k0 l& _# ~

CViewBitmap *pViewBitmap= NULL;

: q; z, o5 e9 Z& Y

\/ y6 v/ d5 G- g

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

% G4 m$ Q( R7 j# L5 H4 R& A

pViewBitmap- >ShowWindow( TRUE);

6 F3 k: l! Z' h1 u+ ^" J

}

8 c+ S% r7 Z E, `, p

7 w8 Z& O( h% `

! p, l/ p& J# L

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

7 U* h' n# H- S$ f# l

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

~, C `1 c$ z7 O, m

6 j% [% f: t6 x; `- p7 B# x) o

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

$ G$ @3 v0 Y( q& x& Q

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

; x; W% o* W# D1 V. E8 J

# N" b8 r9 `* H

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

0 H$ \6 [) \3 e2 q

6 } u% Q O( J' ?

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

. D! \ w% l: m: A

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

3 t! Q) U+ Y2 |* C1 P

* \6 ?2 g5 n9 K

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

5 K: \- t2 ^6 w* e

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

" B8 a4 B4 S3 F# }. P1 \1 c

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

9 P8 e& {& Y+ i# R d+ B; j7 E# l

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

, \1 b4 O0 i! W* k b

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

* @; r. ^* E: @# d& }4 M( Z1 y* k- ^& H

; a9 }4 m; x Z5 |" Z- a

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

- k2 g( `5 z- X9 t3 d5 E

就可以显示该位图。

( q2 w7 k; D2 }) R( O7 |, v

' [; N! w! q+ I9 E" U

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

& s. W5 J+ s5 d; N5 X : D+ t$ h! z$ C# Y. C0 V) ~* j

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

" ]' a0 s0 }" B& `* j' {

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

9 ~ _2 `1 q. p' I' T, H

真小,显示速度快。

% S, p& ]/ A" N6 v% Q

1 @- i5 P* y H$ r

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

1 W$ w/ _' v L7 D3 d0 ]7 J

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

6 l, W8 f# L8 e/ p

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

' e( b! O. f5 l0 s: ?" Z5 A& e1 A+ @

" C; l/ ?; {, G" f

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

9 c- `1 n; @* j( H/ ?

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

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 09:32 , Processed in 0.514476 second(s), 52 queries .

回顶部