QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

3 P2 q0 O+ |2 T( ^' ^5 d- I. z6 V

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

f# n) T8 L0 B: B) M: e9 P/ `

张义云

3 \! P; ^# P$ z/ I

. b! ^- f6 x! s' e

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

0 B9 x# U- v# l( `5 G

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

7 G O: m/ t* T! K4 y" U

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

: [7 R7 u* t/ M" [) v( d; \5 q

/ {4 B6 }. t' _! P5 ?, g* u: m8 O

---- 一、BMP文件结构

1 a& M4 A) v( s: l% {

/ t* g+ e* i) A1 G- B- L

---- 1. BMP文件组成

7 e9 H% G( k4 }9 o4 m0 p

, Z" H% t: B" C# @" ~% H

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

* B6 L8 B( W: f4 N3 P! E

g( H, e" G: ^1 G+ o# r+ {( U

---- 2. BMP文件头

3 v! ?5 z2 x A% @( H* a

1 q; D/ F* Y E! [+ `3 w. E: e

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

, Y8 e) {/ E8 [ _# \

0 V# G* |' ^1 l9 z/ J

5 @- N% Z4 ?* Q

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

, |, t& G8 |: [; _3 M3 C8 H1 Q

" f' |, b2 i- |5 H$ }

typedef struct tagBITMAPFILEHEADER

, Q* F' s! ^- T7 X$ v5 q) M

{

7 _- Q' m! K' P9 ?/ h0 g& Y4 d

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

, V2 U) t$ S" q' u+ H

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

7 C, C$ S/ ?- S

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

& [* g3 T* M9 j. p7 E- r# D

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

4 _6 X" F6 H3 M6 E* y

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

M4 q: R, u! p3 H8 o

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

6 r. d9 `* ~$ e" }# a6 \

} BITMAPFILEHEADER;

! I3 u; s8 @3 M5 W

* A+ s2 f$ o: L" P8 P* j# B

2 {9 `2 L, t9 b, \' p( W" }; e \' C

---- 3. 位图信息头

, L" R, Y: g v' M" w" |% A

----

0 }9 F2 d. ~8 {

+ R, h- `+ h7 O

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

, a( z5 ~& s1 E1 G" I" ]

typedef struct tagBITMAPINFOHEADER{

Q' j6 B! F" a6 a4 h" b

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

0 a4 z2 c& U- R% q5 ^% t

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

, x: |& F; C% l8 H& v) D2 J5 R

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

' X3 J3 W9 |! s2 A8 T% D! D7 i

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

- F9 v' _& S* O2 p

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

+ Z/ ?: s3 D4 `* S. K8 {

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

1 c( ?* M9 Y/ s/ c$ |3 c9 n, s

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

) K, o8 ]) E% q6 T. _4 b

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

: f+ d( i/ O3 A3 y

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

" C: @; _8 N& b4 W# Q

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

, m' m2 H- Z! h% y

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

$ j& E" }# q1 B. f0 I- ]

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

! p# v( @4 v. {

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

" ?5 l( N. [% q' U; A0 X

} BITMAPINFOHEADER;

2 s+ y. p6 K2 N$ \4 K

Q% c( x; p2 S

0 V/ x: C8 x: b [4 Z

---- 4. 颜色表

m7 G2 H0 V. Y( ?, J4 g

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

3 P0 A2 Z& A' |# O3 `& n4 J

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

/ |- Y |8 j/ g( |9 N* X

6 U5 J1 C3 b: o! t

typedef struct tagRGBQUAD {

/ _: W) ?& a& d" z- }) O

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

* S1 B3 j' h* p8 E! o' R

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

# D9 L$ `6 N, F7 c5 O; f

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

3 z4 O% L% M* [. ~' h0 L5 |! |

BYTErgbReserved;// 保留,必须为0

8 b+ Z# X; N8 H) e' N$ x# o% o

} RGBQUAD;

* E& o/ K# P; B. u

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

' e4 E* t o% Z; H v i# ~- o

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

9 |0 s: i. t3 D4 s3 a) a, i$ L

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

. r% V9 ^7 x2 q9 S

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

6 h: [; Q1 Y9 {6 O" X7 a- R Q

typedef struct tagBITMAPINFO {

0 M- ^! Y* i: f4 k: i( r8 m

BITMAPINFOHEADER bmiHeader; // 位图信息头

) `* s1 y$ N0 C+ r6 ]

RGBQUAD bmiColors[1]; // 颜色表

" j3 F2 Z' {6 e) Z) z$ R" j, g7 m

} BITMAPINFO;

" U! p! h' n! P9 Y U/ |6 l9 B

6 }# @9 ?" @: ]0 S1 R" u

( ` v' Y3 ]2 @8 D& M) z9 i: d

) j) B: X3 I* Z. J7 V

---- 5. 位图数据

. u7 w1 G4 y3 l2 T

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

# h; u3 k V( P7 N8 Y

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

/ n0 [! r, Z- i* z

4 I1 ]% j1 X; ]! _( j

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

7 [/ g$ C( P5 D' y0 z" n. E6 |' S

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

; Z! `& N! N/ w

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

& `9 x0 _1 d4 d- f7 D0 b7 {

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

; S6 i( C* l `0 u* ~/ q. A4 @

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

0 m# W) W2 R* \6 z9 G1 G

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

% {" c: g+ g+ K9 A: U& H0 I8 M, V# i

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

/ C/ E. X9 D: x9 f1 n6 s' s3 c1 }" i0 Z

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

0 {7 f+ ^/ Q; z( Y: Y/ }" X

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

! }' y6 w+ B* S: j% c& J

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

8 p# T& @7 o L2 }9 X( _8 ~/ j

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

! H: B: d4 j1 D* t: S6 B& ?- F

DataSize= DataSizePerLine* biHeight;

) c3 l& U# E& r) R3 a& r( s6 S

$ W3 e9 v9 |% f8 _

9 ]$ X2 G- c% [& z& R

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

, @3 ?5 K) a! ~2 e9 X

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

1 p+ [) F0 p6 G, R, T& w. n+ T+ r

9 n( `7 M/ H; M/ V8 l6 Y

---- GlobalAlloc(GHND,FileLength);

! E- i+ C9 p6 ?) q. C" m

* z `3 i3 d6 M0 l4 e9 P- l

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

$ J9 C' W) t5 C7 P

% |7 f9 g w' U

---- LoadFileToMemory( mpBitsSrc,mFileName);

- M" i( o. v/ x; _

& X A$ R! C! F! Z

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

0 n& x& d! \3 X f* T' q

* j# _2 D" z& {) _; Z+ V

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

$ ], O, Y! K }; e$ u* W3 O

DC,

: W3 [2 ]; P9 U# t" h2 n+ B4 C8 i

2 B, k. Z& N2 F5 q

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

* {. C4 e8 `& S$ i2 Z! `/ h

' s) }5 p4 {# p* m3 x/ I# u5 M7 O

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

5 ~6 a/ m3 f% U# P" K' x

_" C9 `0 b2 W# @

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

( o0 X P, ~# c

( U" B' j7 R: F7 W/ c( v7 Q

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

2 z. C% Z) f8 v0 j" F. s7 K6 |

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

8 ]+ |% ^ l- e' E8 n' d# I

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

" s) B. V/ R; x& S8 n4 @9 ~

$ K' [7 ?2 q, Q- y' |- W: x& S0 s

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

$ p( J/ J( A% Y9 X4 {- e

- f. F+ p; n0 h7 S# Q7 s

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

. O8 I% d' F, [- o8 ?6 R/ e; }

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

9 Q9 @4 Z: j) e0 z' u: Z

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

- K2 ^+ ]# x9 v* a |4 {, I

! M3 [/ Z; \2 L" {

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

Y0 G9 y' `% V( _7 I% l0 V5 ^+ x

6 E) T; X: N/ Q7 q

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

# d' t8 O6 k# X F: U, y

, B B' d4 y; }2 E. c: o

---- GlobalAlloc(GHND,FileLength);

- _- U+ j* W2 a& C4 }8 \9 ?

; ]- q, f+ J7 n# [2 A2 ^

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

! ^4 f! H4 ~. T9 N/ Y0 N. `

4 [6 ^( C Y% S& R, ^. i* X

---- LoadFileToMemory( mpBitsSrc,mFileName);

4 `9 \: a7 [2 v& v5 i

V' p! f M6 M' M* P& s# n; w

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

# p' s( m; n! ?+ Q* _; \

' F, O" e' V; ?3 E0 G1 ?/ O& ?

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

( q$ I5 v2 i6 \+ d2 Z8 M8 c

: V; t4 b5 ^( n* J, l& @

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

9 ^- T9 a V5 p X0 t- A

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

3 p0 e8 a* H% C

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

0 R w+ k A% N7 b5 v

1 P s; H7 Y3 M2 \

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

6 I9 d7 s1 Q. s' `$ X' i

* P1 i9 D( u S. h( d

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

! l( O0 }; a# I$ _- \% w% N

8 w2 n: S! T4 K8 O6 R

HDRAWDIB m_hDrawDib; // 视频函数

4 C- _# s& E3 x7 X

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

s' {1 a4 U1 ~- j

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

- h/ W/ A2 j7 c" U' K

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

d; R a. k3 k+ ?* m0 Y! M# ?

( U( \. Z6 G ]. g) Z: ^

9 O9 f, t/ f/ y0 G- D, y; \

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

4 L# O' `$ D- h) y$ q

---- m_hDrawDib= DrawDibOpen();

' [8 r1 S; r& o! \& {/ v

! V+ x8 w* V/ Z+ X9 f% l* P

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

" A1 u8 ~; m* ^* f5 q% W

% `3 w( D) W3 g- N. Q% ^0 c9 _

if( m_hDrawDib != NULL)

! [, i' e# P4 p5 }+ Z0 p

{

5 X2 j; z/ w# |' E, |% D/ Z* B

DrawDibClose( m_hDrawDib);

/ S; q3 N5 }- z8 r( i, g

m_hDrawDib = NULL;

8 {# Y* P( V+ a" T0 T- g+ i( G4 z% p

}

% d* z( ^% ^) m3 R4 W6 f6 F

( z' q5 N, b' x# u

* q) o9 O- Y" h; i5 B

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

6 y: J4 l/ \; @. |: V

voidCViewBitmap::OnPaint()

9 J, O: k6 `5 v

{

& Y4 e/ p$ ~3 I9 O: e

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

* h7 a+ |& s# A! V, O2 a

GraphicDraw( );

C7 [+ a+ o3 h# U

}

" K. ]# z" L1 x% n. b6 Q

& o6 N6 d3 m% Z# T6 K" K" w

voidCViewBitmap::GraphicDraw( void )

- i/ M" |+ B1 h% E0 L

{

4 s# G4 r/ x* p% N7 h/ d: k

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

/ q7 C" i/ e% O. b1 P @" _) e, v

BITMAPFILEHEADER *pBitmapFileHeader;

, K: X* T9 N; R' v+ ]7 {

ULONG bfoffBits= 0;

- o$ Y# K! y3 F

CPoint Wid;

+ l% n! u4 I+ U0 E' n+ x

: {8 c" y# L3 _8 q; L

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

+ G* Q. C: {1 m, U! S

if( mBitmapFileType < ID_BITMAP_BMP ) return;

3 j% c `% s, w7 j- F( b ?, k

R$ h3 g+ v; j- E2 Q* k( W

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

" f7 G' M) Y- a5 ~: z" }4 B5 I" D

// 准备显示真彩位图

2 [3 ~, D7 e. a$ W' l' Z

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

0 P: V5 H3 _0 g4 [! M

bfoffBits= pBitmapFileHeader->bfOffBits;

3 O) D* F2 S6 w" `4 r

: ~+ b9 Y% A: Y" ]) v8 o& L2 ~

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

, M" ^: R1 }7 ?$ h. a& g

6 v s: G4 Z7 S: S% H- @- l

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

: F8 E( ^1 f5 c J* R

{

W N; l0 b. ^$ p- q0 j

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

+ a( X' o- p, ?5 {% O

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

# z1 Q1 I- N n

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

2 \* i+ c0 y$ z# }

// 建立位图

3 M& B# J/ R! J; A) v$ L5 u

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

0 G/ e# q8 n3 s+ m. j# }9 u; W

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

3 T8 x9 N) o& p: Q

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

+ t# y, h4 O3 n) m, y

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

3 \% d2 r* B# N {/ ^

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

3 k; Z0 M4 T8 E( m& `0 w0 x

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

! z2 \0 D& `+ i% b1 Z

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

; Q3 Y/ _6 ^9 t+ Q2 w

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

' L5 V ~+ [! I9 V* U" E$ e. n l

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

0 n0 A" t( |' j

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

% v# D: T7 N& z! w0 l1 L1 ~5 I! [

( w* |8 H0 W: `+ n% B' j$ d$ N

if( mFullViewTog == 0)

9 _8 d2 b: b; x* c) X% ^

{

" W. N! O4 L9 t! Q) n6 }5 R* n

// 显示真彩位图

* x; |. K9 i) z1 N% E- Q3 P' E

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

# m2 ?/ a0 m, u0 E* S0 a

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

; a) @: b! P5 T: D+ |1 L& c

} else {

' ?# h* `/ Z% k$ B: |7 I) Y% J

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

. f) e2 }7 y+ G4 W! A8 l

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

{ _" C) Y' |2 \& ?

>biHeight, SRCCOPY);

- B# T' o& B" B' `

}

$ E8 [& V. o4 z

// 结束显示真彩位图

; V9 Z6 ^- u- }5 s0 S, A- I5 X

:eleteObject(SelectObject(hMemDC,hBitmapOld));

! x. ^- r: k' S+ l" Y

// 删 除 位 图

$ d4 k# P3 p" P* F! m [

} else {

7 C) J6 V0 a4 p# a9 e, ?* F- N1 {6 G5 i

# @( e& x0 I% h; J5 X% f

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

" G5 c7 f" m. q* h. ~. J/ f& F) r

/ f/ M# m5 z' O0 _5 Y; A5 p

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

. g, k* i6 o2 l( \1 L; n* i

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

- \5 l# `6 }% X& X

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

% J! X% |8 `( [, n! p: V# q; c

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

- F7 s8 J$ g! e8 {9 j6 ^

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

& h+ `+ ?, N1 o9 p

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

: S' Q4 D% k! g: D$ \. T

4 N- Y2 K, }9 V+ z0 @. {

// 显示真彩位图

9 b9 u" P3 H ?" L5 v2 b

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

3 u0 T ]$ B0 F9 r6 {7 f! x' Z

3 m$ l$ K2 z$ N7 ?1 l

if( mFullViewTog == 0)

6 B3 n* x& r% r p

{

( j, M) m2 k; C1 t' Z/ j1 M* D

Wid.x= mDispR.Width();

; J3 X3 h7 Y' C) C) s, d; {# s4 E, j

Wid.y= mDispR.Height();

3 _/ q. S* w0 b6 `$ z! d j0 L5 e% A: v5 [

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

& y6 a4 f' t$ |# f8 v4 ?$ G2 x! F! Z

if( Wid.x > mpBitmapInfo- >biWidth )

% C- z6 _6 X/ n* H9 ^$ r! A. i

Wid.x = mpBitmapInfo- >biWidth;

9 j$ C5 _' Q+ n- E8 I6 V* I' o A

if( Wid.y > mpBitmapInfo- >biHeight)

$ v& S/ ^% _* ?: D8 \

Wid.y = mpBitmapInfo- >biHeight;

% y3 O6 K* s6 H; B

/ Z" E+ X W# T& M% d- z

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

4 _8 A$ ^+ [1 J5 I3 Y1 i2 K

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

7 M7 Z8 j" \3 F* x) b2 p" a: ]

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

+ t5 R$ h' @' h& e; J5 R

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

' C/ [$ D# {* E" R8 w7 f5 J6 @

} else {

& g9 d. k' ~. N* F3 r4 n, E2 i

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

+ w( z# N* |2 ~7 B$ ]1 f+ W

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

6 {' [0 B/ a: n+ ^

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

1 l/ ^- z$ c. X" b0 J: c1 _

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

; S3 G4 l- Q3 A! Y6 A- r

DDF_BACKGROUNDPAL);

5 l2 ]" j1 ?0 [3 i* R0 R

}

1 M0 |! x& B: P, B1 A

}

" a8 L. r- d/ M$ v5 P9 g

return;

. S" J+ V! ^, C/ O

}

- e1 i% Z0 }. `8 B5 p: I7 g

% I3 H0 q/ p% k o; V1 s! G

0 k& L; }' x, r4 Y1 o

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

4 t' b6 x- v6 w4 W2 }% g- `

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

; k# [# N; z$ z

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

- g1 b# R1 k+ C2 d$ E# p

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

" K+ g4 d) l: v! ^$ |* ~6 r# T: K2 n1 Y

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

# U$ [9 q5 i" w1 {" D% r: a

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

/ f% u1 u# m: `- k6 b" a

& P" J; Y0 J7 M/ U% O5 p5 s0 s9 P

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

9 y# E/ F) h* d! [ k# [

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

1 O' D) X2 X! P0 x+ _+ t" `

- A4 u3 ?5 W/ @7 Q# m

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

0 `: B+ p$ R6 { r8 m0 h: ^( |. I4 Z# _

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

2 [5 F8 |0 X9 b( _( A D2 _

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

& P. U* k8 ^; p# E

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

6 ^- U' G d r" t

。代码如下:

0 v9 r, N u3 R

$ S r( w! q# @% f! X

void CMainFrame::OnViewBitmap()

& Y6 f/ Z+ y" N4 g

{

, B: F3 D# f( D+ ^/ U" n

// TOD Add your command handler code here

9 U v5 a7 K# o. u9 C1 a' |' F

CViewBitmap *pViewBitmap= NULL;

/ L& t: O9 t6 y& o5 G) O$ S3 S

0 j8 O; Z4 u8 j( p, u; W: _/ c

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

$ x3 j$ g- K. i

pViewBitmap- >ShowWindow( TRUE);

8 F/ O1 l' {. s9 G y! ~- |

}

6 {2 h0 g5 }- k1 W" j" O6 F6 E

1 j/ b( o8 o- ]

& w5 Y3 Q Y3 }4 b2 U

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

! l$ F! l7 G/ z9 {" J

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

* ^) U6 ^) ^. f1 i, x2 S. v4 N% o

9 C2 ^: q( H8 q# O1 g- |5 r+ m; @

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

- D: L1 G, O- Y0 R/ P) B

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

2 ^5 E$ |6 F- o- g& R' R

! K9 r5 ~6 O/ D' y

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

2 W) E5 Q. N+ j6 f6 o3 X. g4 _/ n

5 s/ Y- z; w, R% f: g

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

5 s' Q1 p5 x4 t2 q0 u

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

% g& ]- g& l3 w2 A5 u6 a

) ?8 }3 w7 p8 r& D) Q" g

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

$ K% {% ]; [6 _' j( a" Z/ x9 E

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

1 i, ~4 M- K- @! _' A, ?: E- C

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

& q" j- m$ ]# X0 G7 d# @: d$ \& L

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

! a& r- J6 }, D$ i, ?5 [

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

$ _) L1 P! w4 h8 ^0 ^3 C6 I$ q- q

! f0 |2 Q* `4 U$ {* @+ B/ X

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

5 V8 ~8 `! ^% Z5 c3 L

就可以显示该位图。

) \" j2 x& A' T

7 x6 u3 B5 {6 k0 g+ O8 p( i2 K/ {, k

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

6 u; Y6 H$ b8 C ! m# q2 _$ g8 [( C

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

, p M: [% K- a

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

9 j* j3 `) u$ I8 }

真小,显示速度快。

( B9 Q `& J8 m2 S1 C2 T7 L" F

; u/ @: m; z2 a: Z

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

1 l( f/ `! R& g4 x/ U

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

( g& G' c' w3 A% T( Y+ j

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

/ K: u0 v7 f- I

* h" I+ i( h- f9 ?

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

/ j2 N5 J. H3 m6 m8 _

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

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-19 09:42 , Processed in 0.430740 second(s), 51 queries .

回顶部