QQ登录

只需要一步,快速开始

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

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

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

823

主题

3

听众

4048

积分

我的地盘我做主

该用户从未签到

发帖功臣 元老勋章

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

9 W- ]# x- @# k8 y" i. S

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

7 V/ d: H0 h" z; W& ^

张义云

- K, Y1 u, w9 T+ ^7 L+ P0 ?

- F* F% o) L/ a

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

0 L7 M" ~7 _( ?; _! w; P

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

7 g- a, k I. e+ N

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

. Y. n& M; E: [5 Z3 B8 P0 ^

- o6 K3 ?/ o" z+ Q& k! A& E8 S

---- 一、BMP文件结构

( i/ [5 y0 e$ Q& f1 B3 Z2 v

8 L+ q, b6 p; m: @/ G3 E( l, Q

---- 1. BMP文件组成

. N- o% P! G8 X1 Y

0 w% j; j) `& H: D. e

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

5 c' R% g) i6 B! v& \, i

6 k0 h' i+ s( `" ]- S0 |

---- 2. BMP文件头

- q3 |* G! ?, ^0 i2 y

. O- s- I6 h5 W7 R

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

" ^% i1 X8 V6 W) j" H( a$ s

7 ~: {4 k8 K- c/ N1 Q" _- [

: m6 v" W0 \) o R6 a5 P

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

* M( b' p/ m' ?0 a3 {/ H

$ p9 b) y7 h% Y1 @6 r

typedef struct tagBITMAPFILEHEADER

! e# g; A5 r$ y$ g0 U4 V. U' m

{

# y% r* G g+ J$ m8 N& @6 u) S

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

; ?1 T9 |1 |, N( A4 V- E& W- C

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

0 u X) [ K; L* v( `: e* I

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

0 C* u. F n% ^! M7 a3 M7 o

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

: g' u2 p( Z- ]' M

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

' f' o# h4 N- b. w

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

5 t7 `2 C, e' u% }3 j$ v. R

} BITMAPFILEHEADER;

2 d9 Z5 [$ R) Y4 \, F9 ]2 E9 H

" R0 J( z* X K! {; v0 F3 D, M

& `+ }8 O- v. P$ D! Q: e- M& Q+ d" M

---- 3. 位图信息头

' e% h( S- I6 }8 |0 k& | T0 \

----

n: C R6 u: ^; D, t& b

- n( X8 w. J4 x2 r/ M+ U$ m

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

6 d6 I# [( K+ R H+ b5 N- ?% z: A: N4 g

typedef struct tagBITMAPINFOHEADER{

2 I/ ?' T X) ]1 b

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

" D w8 _4 [6 U( @3 f D% u- A) o

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

0 L. j6 t) |9 `: x- Y+ v

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

6 G+ z( b; ?: M {: o% m

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

8 K& ]! G+ |! Q0 G; J- x) r

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

, V' K7 K s& N) k0 d5 z' u

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

5 p: m: `5 Q& M0 t( F2 O

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

`) n- P+ D, i9 u$ o5 V$ m" T1 b

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

2 \ Q) i. g! K t3 y- H9 R3 |+ B/ Z

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

: ~( ?0 T3 q- A6 W) V9 {

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

* H) f/ g% v3 ^' L

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

; X" s/ y- x+ F( f

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

5 v# w! b* c) [' B4 F- {+ j( |

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

u8 k0 G: [' Y/ |4 t: W; d

} BITMAPINFOHEADER;

3 d6 t, D: U! p" G: @5 |

0 {) x* M* M2 [- J/ j

6 @3 O5 J% H# B, H( V3 E

---- 4. 颜色表

9 n" j- L; \# D! H& p

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

F: G3 g) ]% `6 j1 p

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

* @) s3 ]) y, f( O6 x

% d' _ Y- C/ P6 I: `% v o. C6 b

typedef struct tagRGBQUAD {

' `, M. c$ }1 e# B8 T

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

9 P% ^; L% L& L

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

# F" w5 V. b, Y0 e* W {5 c# e

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

- \9 \( s+ {3 c: X

BYTErgbReserved;// 保留,必须为0

0 l% y" Z9 ^; y# o

} RGBQUAD;

5 i4 E/ J5 P% J" \+ |" m. X+ S2 v

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

# E+ m9 w" U9 I1 J

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

& K& M# |# G( |/ f; O

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

8 e7 x4 ~9 q6 l2 y, f

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

% t; U F" T0 G5 l* y' m, c) J

typedef struct tagBITMAPINFO {

+ j& G* O& {' u

BITMAPINFOHEADER bmiHeader; // 位图信息头

3 M4 E- \4 \# R/ \9 F5 s3 e

RGBQUAD bmiColors[1]; // 颜色表

" e% c- A1 i x8 _9 b, s) z

} BITMAPINFO;

" n! [. J9 T ?

/ N' e. h5 v1 m! i% v' r/ @4 K5 X z

7 E5 ]9 l/ g1 }/ K1 E$ a8 l3 [

; |2 [; c @ ~5 E

---- 5. 位图数据

) B+ P8 E8 ]' b$ i

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

. g3 u* }8 h) K1 u& d

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

7 n/ J# D3 B0 i [

; o/ n- Y: b8 C- Y

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

3 G* \. R7 c p& Y" Y0 A

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

' z5 t) l4 B1 z( e- b5 @

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

$ O: ~1 ?0 A1 g- m

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

$ }" ^$ Y! @ H, \) u+ u1 {

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

5 ^* h2 s! K7 Y- V g0 u9 |1 y

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

U. y- @' F; I/ `; N8 y: b

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

' Z) t5 z9 v# g3 ^

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

! r% w& y( Q8 C4 E+ a$ E& S

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

" J c) _5 a' s9 z5 f

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

6 o1 N! H9 d' r% e1 H, j; }

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

4 J' E0 q/ [1 l- h4 z/ K' l

DataSize= DataSizePerLine* biHeight;

% C4 S0 I: T- D$ R5 G# R! b5 B

5 Y6 @1 M; N& l q

6 O, y0 g: p$ M3 @

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

! h" O0 ?5 P9 B: ~; u7 u5 Y

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

. ?( h# ~6 r# `" a6 B% W

" n+ H7 M0 o% f4 G& P) p

---- GlobalAlloc(GHND,FileLength);

0 ?$ Q) R) `: v$ T$ C' p

0 ?6 U s6 ^) G1 S: L

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

. d8 U c) t% @- I

: D I5 o( f5 y0 H; X- }" R

---- LoadFileToMemory( mpBitsSrc,mFileName);

; O: g% c: F! b: p ?

+ V. m0 W8 g( X7 X3 a8 X

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

' k; O1 b. n: U) T+ R: N! z

2 P& n. `) C) p

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

( P1 x. D: k" P' J

DC,

& u$ |) |, X3 _' W; V) L" X5 ~

9 x: k& D$ a4 E8 M

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

3 c6 N3 M1 k7 D( _6 K

H2 }! j2 S6 x& b

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

# l0 B( ^* U. k+ x

! G; r, j8 \' \

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

. h- h! f/ m; c* e5 N2 w* {8 P" ]

$ c% a3 E* ?: R) G7 F9 q( c2 @" m2 n' o

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

& {: b* V" ^- }# H! Y- E

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

, X4 z/ z6 a0 I" C/ D

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

$ F$ P- a% M* h& {( S

( O" X+ Q( A: t! h6 l: n6 S- `

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

" Q+ @& U( w# z' F

! o* [0 \" h/ _: K/ x$ Y

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

& s: R( Y6 E1 q) P n* J

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

! A! B4 Z7 O& \/ X" c

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

2 k- t9 b( ~ u' s$ X6 N" k

1 s) Q! J/ S2 z6 T5 n

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

. H: K/ ^3 i9 l# N- R/ u& a

# `' i/ p% Q* X

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

: ~0 S& H `; D$ Y! T) n3 z Q0 Y

+ x2 {! b$ C3 u

---- GlobalAlloc(GHND,FileLength);

9 o, [ ~4 \, V

# U* _2 _+ X, q! A+ G0 S$ R: ?

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

8 r& ^- T( S2 z! t

6 C8 _7 m N5 N( U* {) c& P+ J

---- LoadFileToMemory( mpBitsSrc,mFileName);

' I4 S1 M* r P2 M9 @ J

* H- n. J3 Z4 Q) K0 R( f7 D% N

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

: y+ M, F+ d+ L: f" B4 ^; A

$ X' z0 `0 i- o8 I( ~8 P: C6 I

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

" V1 f- [# v9 @2 I. I6 W

3 y" j7 F# ^6 K. a& j% P1 Y2 M

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

5 v8 ]. ]7 A5 b; l" u Z- w

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

+ V) n+ n8 M `8 a

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

: K8 J2 a1 I* T1 R7 F9 M

7 r" F( j. f6 ? R8 s4 y

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

- K# V5 e- V% H1 u

4 _9 I, Z3 S- o. E( j ]2 `/ R

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

8 W& T2 L4 E6 a" j- I' Q

8 G2 A' Y" T: H" n

HDRAWDIB m_hDrawDib; // 视频函数

$ P& g) h# W" y3 ?

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

; i$ [5 N: d% G' K4 O7 F/ c

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

) k+ U: F; S( G

BITMAPINFOHEADER *mpBitmapInfo; // 位图信息头

& y; r3 R5 y8 `4 X! P3 e% V

0 D: ^6 h L0 U

7 p. R; M( P+ W

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

% p) Z$ F3 s9 i, G

---- m_hDrawDib= DrawDibOpen();

- ]6 T% s6 D' q

, f l0 A4 X9 A+ i3 S1 N

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

9 X: j4 J g: h

6 r8 J% D. c! R' W# }1 G

if( m_hDrawDib != NULL)

5 r( U# H) O+ Y; i3 ~- I) e+ i

{

- p' e3 v/ V7 J' m; L1 ]% V

DrawDibClose( m_hDrawDib);

' X3 b* V* k7 O+ B( J* y @1 Y

m_hDrawDib = NULL;

1 N `! b% t2 C0 i: b b

}

/ A: S3 |# k9 G8 l

. q0 B( {1 V Z; M# o6 k7 Q) H0 d, [: h

$ ~& I( ~3 I/ y* p7 i! `1 l

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

: ]+ R; d. I" p* f1 K! s

voidCViewBitmap::OnPaint()

2 i- p. W/ a/ y" A, s% C' U5 z

{

# ]3 i2 D. Z$ `) A; B* v

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

5 B% ]% ?, l1 p0 p! x1 J" F- H

GraphicDraw( );

4 y7 g# a1 o5 r: r5 w

}

8 D9 \/ X) U# ^& ?( D3 ~6 N

$ s4 `. t, H5 }; s% @& Z6 o+ k# V

voidCViewBitmap::GraphicDraw( void )

7 G' Z' [+ a+ J

{

2 `6 N5 U% H" b! m) ]

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

3 y& G3 X8 F) P

BITMAPFILEHEADER *pBitmapFileHeader;

6 @5 q# D4 o, B8 B& S+ j3 A2 T+ {

ULONG bfoffBits= 0;

/ x0 g/ Q9 P& u! L. I

CPoint Wid;

: [- `( h$ X7 Q+ H& A+ _6 i

7 C2 X Y9 r2 O O. ?, q

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

. L4 ]! Q, K; o5 p. z( v* D {- @

if( mBitmapFileType < ID_BITMAP_BMP ) return;

+ Q0 n2 |" a: l/ h1 j

: Z2 n4 g0 p( a7 w* F

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

1 ^! M9 y8 C* v9 h8 E; A. Q& }

// 准备显示真彩位图

5 A8 v' e0 |* {

pBitmapFileHeader= (BITMAPFILEHEADER *) mpBitsSrc;

& c& f" o0 W3 x* J& o

bfoffBits= pBitmapFileHeader->bfOffBits;

/ O% C% W; c6 D! K2 l

# W- U) o. ^1 i! f' l; G* F: t

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

6 M) K* T1 g6 M! P3 {

* X* j h0 O5 B. Q: q% d

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

% `3 S/ U5 p& v; S* C' y. a

{

, H: ?) ?" f% w, j

HBITMAP hBitmap=::CreateDIBitmap(dc.m_hDC,

* S% N# F" ~" D. X

mpBitmapInfo, CBM_INIT, mpBitsSrc+bfoffBits,

4 T" l- `/ @3 g

(LPBITMAPINFO) mpBitmapInfo,DIB_RGB_COLORS);

4 k- _% y3 C$ i+ E" K$ P! D

// 建立位图

/ h! X" e( a5 D) r7 T" m# N7 h

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

3 V+ m' i# K. a

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

! s7 E; U) @+ h* ^6 o+ p; r

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

, `' X! x* l( w

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

" x1 A( R' L* |( M* r

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

, X& `" r; o; C6 S9 I) Z

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

5 m/ ^' u W# T' S i! D

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

o5 c: T& s4 X/ g. J$ h+ e

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

3 Q% s: C; a5 o

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

2 ?3 [! F/ ?' }/ F* O( f

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

- r: U; ?+ X1 O1 i; r' ]& O

5 ^8 `" H8 n: E+ X7 h5 w5 _# b& Y

if( mFullViewTog == 0)

: e- d2 z3 L0 b; r) u

{

, e; d& y# K; J+ `4 B% I" C( q$ n

// 显示真彩位图

7 O" ?- r# x2 V o) N

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

9 B) i' z5 d& {1 L! S9 ^: e ?

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

5 c3 e; g& C5 O7 N6 {" u1 y

} else {

; Q7 [$ _. l- d

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

# G: h5 M1 \) }+ ?, H P

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

. b7 Z; W: Z3 e6 r- u

>biHeight, SRCCOPY);

8 ?) W' I6 H4 W' s7 Z

}

& t( |# P0 N8 x, }3 F1 m

// 结束显示真彩位图

; B( Z5 w7 o, H* B, P

:eleteObject(SelectObject(hMemDC,hBitmapOld));

) r# @! H6 C1 G& R

// 删 除 位 图

' F$ H) t ~8 X' }" E

} else {

0 b5 b. P0 b: e# J1 I$ S

$ u7 y: k4 k: b" y2 \

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

7 d5 k2 t* A; {; a. ?8 d% g

4 _7 I8 q) u& `& {' o2 h4 s0 O' \

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

* L/ N: I: w3 n) V1 Y

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

- G+ b6 u2 i# k l" w/ Q! T

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

* g; W8 ]( [& d% b- H: w h) |

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

0 w! e9 F% k* \

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

: q( c/ M" }/ C* E' y

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

3 T1 _' c- b: q3 {, G) w

& b) R7 ~1 x$ M) i y

// 显示真彩位图

; O' i/ R5 h) U9 \1 h

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

- M) D% u* q; [$ j2 p

. @1 r" T& }+ O! C2 n' O7 S

if( mFullViewTog == 0)

* K( V. P9 S7 H8 h

{

3 e3 ~9 V h3 o

Wid.x= mDispR.Width();

' U; s) i/ {( ?! G6 l3 Z

Wid.y= mDispR.Height();

. S- [( U. D4 W/ k6 F1 k( w

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

* ~7 x! L1 d$ c P

if( Wid.x > mpBitmapInfo- >biWidth )

' S+ r! U" M% L

Wid.x = mpBitmapInfo- >biWidth;

A$ ~/ E H2 y* ~$ k0 d" {, j

if( Wid.y > mpBitmapInfo- >biHeight)

% n$ |7 Q2 r8 K( k0 c

Wid.y = mpBitmapInfo- >biHeight;

2 ^$ V* B6 | C

% J5 `8 B3 h# q- U

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc()

. K2 f8 X- }9 y' X- g. v# \

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

9 }' g) F, F$ R3 d2 A

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

0 K. ^4 ~: F+ p- r; x) d5 a

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

6 } h$ Z3 F% B, J

} else {

* `0 f+ v( Y6 s8 f

DrawDibDraw( m_hDrawDib, dc.GetSafeHdc(),

1 I0 R' U2 }; i# T- T+ m

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

' ]9 c; e1 k) U

mpBitmapInfo, (LPVOID) (mpBitsSrc+bfoffBits),

# E: D! a j5 \/ E: m, f( l/ D; B

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

7 c0 w) V- E2 o8 B* n; n

DDF_BACKGROUNDPAL);

' v! [+ E8 n4 u5 h

}

`9 S9 g% V! Q" L9 B7 i' q

}

3 R# T- ?% w' m' U: j

return;

* m/ F" B- d9 X& C

}

. A, C$ x: V7 S6 N0 w& |9 i# v" f

% \3 p/ u. F4 p0 D5 ~* m

: \) {* s: d% |! B6 |: A( u/ X

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

8 Y- ^4 I! n2 x) g$ m( L

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

' V! a, Y0 x6 R0 [& t

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

- _$ v. v" I* w# q4 m( L

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

& w4 J$ b# G) k

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

( W9 d) r4 k+ t" O5 V

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

! r. y$ ~3 n* x6 ~/ ]: h

! A5 m# U$ f; s! @$ x! u0 i) d

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

& E0 E( \; V, i" K' g& F

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

- D& Q( P2 | h3 G* Y, U

9 }: H+ N ~- X# {% i% p; N) c4 g6 ~

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

' b" x/ f; f1 g7 r& n& k9 |

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

, q! b4 f- B* H. y7 Y! b' J

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

& c- T/ _4 \$ c! @) |

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

' u- ]* |' P N

。代码如下:

' u1 C3 h# {; q9 d& C3 V0 B. b

0 F% F4 J7 b! R9 {" O0 e4 ~

void CMainFrame::OnViewBitmap()

" ?; M* T% W2 d1 J

{

# O4 @" f1 a) `# [5 O

// TOD Add your command handler code here

# I% ^3 J" X' N

CViewBitmap *pViewBitmap= NULL;

. j6 l9 |$ G6 n) N# T

/ ^3 Z. E& T R: v* J

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

( r6 l' @( H7 K4 P3 x" ^. J7 T- G- y

pViewBitmap- >ShowWindow( TRUE);

" P# `: x/ `% C( f3 C

}

6 }9 H4 k* j, d5 B) O

S, k. e" ^4 T" l; n9 F, _

+ p7 [% p J' h; g# ~

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

; ~6 U F1 ` d2 p$ K

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

5 u$ J7 |& q- b; h7 N6 u' H% G) K* A K

4 ?) ], P) Y! d! C9 v% T

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

6 ~- v# ^& o" c

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

5 L I+ L' s7 V8 o2 b$ a

' z. O6 E# G p' F

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

7 A a9 _9 c! B! B+ n

9 Y+ a( R2 ~ d

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

6 D% O& }9 w% Z, f

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

1 R, h2 P# m5 Q

^2 @7 u4 | L, s

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

0 S0 @* l+ i! d8 h% N

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

1 U$ p" y% c: ]& \" M5 M( H3 y

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

8 O( o Z" f- e% s$ v

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

$ ?# q% P' R; m1 o

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

; O2 C( {, l$ T* r! s

' N1 N8 X2 X7 S W9 g1 f

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

/ i- A) p& T0 `- \' |

就可以显示该位图。

* p/ o, ]" E0 A

0 P2 n: \& l$ C

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

" A/ I% n+ L+ O# p G ; k( m; G% J9 k$ g: Y

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

7 }* l' F; L/ Z5 i& @* {

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

* y+ F, b1 w- H

真小,显示速度快。

! l- i* {; F, A$ Z0 u5 g) t1 q

6 g& {% N: e- y6 Q x

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

# ~! L& z2 [8 m' p3 [+ y

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

( d4 v+ @" C. I2 L$ E. `' S

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

4 v0 h5 e" {9 V9 r7 d# {& U& R

; J: O, k: l7 z& v' L

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

( _( v6 C* b$ ?0 a( r! w# j; l

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

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:33 , Processed in 0.448944 second(s), 53 queries .

回顶部