VC下显示JPG,GIF的图像的显示就程序开发过程中要用到的一个模块,今天我们就来谈一谈它的具体的实现方法。: a$ _, y9 U: L; A1 L( a L+ M
在显示图像之前,首先要获取到图像文件的存放路径,这里采用标准的文件打开对话框来选取图像文件,文件名存放在CString型的变量m_sPath中:
6 a; Q9 k; N, d3 D f) N$ D# r9 [ CFileDialog dlg(TRUE,\"jpg\",\"*.jpg\",
% A$ h4 }) W1 @" s OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
8 V* Z7 e$ R* S% ]4 N9 A% P. k9 C \"JPEG文件(*.jpg)|*.jpg|GIF文件(*.gif)|*.gif||\",NULL);) p/ m# P6 x4 ?$ t8 x% `. G
if(dlg.DoModal()==IDOK)
( r0 i' B& ]( R* L1 W; v# ^ {
' @, [; Z2 T3 k m_sPath=dlg.GetPathName();/ P! S- e. Z. M: {+ v- e6 G
Invalidate();4 L3 ^3 W+ c& C' W7 V p! O
}
) D* u) c- W0 ?8 C$ ^$ M5 n 为简单计,图形显示的代码直接在视类中的OnDraw中编写,首先打开文件并判断文件的可用性,并把文件内容放到流接口IStream的对象pStm中:& [6 S0 k5 {4 R7 X9 D6 ~9 j0 o
IStream *pStm; \6 {2 w3 M0 F% `. M
CFileStatus fstatus;6 Y# I/ d: B( @) A& C$ Q& Q8 s* E! z
CFile file;/ f. ^4 f2 S) {& G7 Y* W
LONG cb;8 X- `* \: f8 Y) f' c
……
2 m+ b7 b' r) p) _* Z0 ` if (file.Open(m_Path,CFile::modeRead)&&file.GetStatus(m_Path,fstatus)&& ((cb = fstatus.m_size) != -1))
' F0 S* l& T$ G9 @% Q* f3 H {
* [0 q+ c1 }) p- ]2 R! a) Z HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, cb);' }0 k% I8 @1 L( W
LPVOID pvData = NULL;
+ A: |1 y+ g% O- o2 N if (hGlobal != NULL)9 G9 G2 E1 _, N2 K/ p
{! `' r$ G( ]2 _0 x5 D
if ((pvData = GlobalLock(hGlobal)) != NULL)3 F4 |, }& c' z
{0 S9 D8 A: c5 t7 G! T7 b
file.ReadHuge(pvData, cb);
' D" Z* W6 q1 t* @# @ GlobalUnlock(hGlobal);
; G' T$ ^9 K; L7 a6 ]% U1 A CreateStreamOnHGlobal(hGlobal, TRUE, &pStm);
5 P+ L$ _/ U0 n0 M% L, Q9 g- ?% R5 I3 w }
( ?0 I8 r L) A$ O- {$ s }
2 R) X# n( X h7 _ }4 Y+ O" ]% Y& I3 D; K5 U8 z
然后,就直接调用OleLoadPicture函数从流中装载图像:
* s5 L+ `% O/ X9 h IPicture *pPic;
% o4 Y9 P$ D9 z4 {8 @' w4 g ……
* e. \' W* i" j; K2 r, K OleLoadPicture(pStm,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic));8 q! L( b9 Q+ _
由于该函数有时会导致失败,所以应当用SUCCEEDED宏来做一些适当的保护工作,只有在数据装载成功的前提下才能继续下面的图像显示工作:
) L9 n4 x: Y, u) F" c1 M if(SUCCEEDED(OleLoadPicture(pStm,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic)))
" O, r/ m S% J0 g$ t {4 O. r0 a1 _/ a+ O$ L# e
OLE_XSIZE_HIMETRIC hmWidth;8 ]8 B- w& o [! Z7 k, n/ |
OLE_YSIZE_HIMETRIC hmHeight;; r. W- f0 x5 E- S
pPic->get_Width(&hmWidth);3 x! y" O5 _; K7 f3 G# [# Q8 m
pPic->get_Height(&hmHeight);
/ v; T8 t* A% D, x; T/ d double fX,fY;
! K( X% |( _. _! M- E6 L) r ……5 ~5 L% k% X+ K x. G
fX = (double)pDC->GetDeviceCaps(HORZRES)*(double)hmWidth/((double)pDC->GetDeviceCaps(HORZSIZE)*100.0);
6 E- Z3 \; H0 m, P p7 m fY = (double)pDC->GetDeviceCaps(VERTRES)*(double)hmHeight/((double)pDC->GetDeviceCaps(VERTSIZE)*100.0);& j F9 {) u3 c$ F; K/ ~
if(FAILED(pPic->Render(*pDC,0,0,(DWORD)fX,(DWORD)fY,0,hmHeight,hmWidth,-hmHeight,NULL)))
; c$ F# o% K6 ] AfxMessageBox(\"渲染图像失败!\");/ F1 v% Q# I, E& N. Y1 k3 C1 j( }' p
pPic->Release();
; [" T% @2 j% E }% r4 k7 U+ Q A/ ~4 H: N
else
! ~- n$ |6 j5 I! a$ ] AfxMessageBox(\"从流中装载图像失败!\");1 t8 N; n& H: Q& }2 L. |# G/ z/ T$ x
其中,显示工作主要是由IPicture接口对象的Render函数来完成的,该函数主要用来将图片的指定部分画到指定的设备环境的指定位置。原型如下:) E5 _+ o' c s7 z0 i2 O: f1 ?; R
HRESULT Render( HDC hdc, //渲染图像用的设备环境句柄
4 m1 q! h7 n+ k- J! S long x, //在hdc上的水平坐标- w# ^ z+ w. F7 q: A( P% ?
long y, //在hdc上的垂直坐标& v9 r2 j, y6 e( t* t) r0 t) w' i
long cx, //图像宽度3 V/ x+ o F/ T, S, L
long cy, //图像高度
4 V n; u4 S9 C$ j+ W: w: w OLE_XPOS_HIMETRIC xSrc, //在源图像上的水平偏移
2 W! j% J; Y, \# B OLE_YPOS_HIMETRIC ySrc, //在源图像上的垂直偏移
! k* @# L' O a; F' Z) M OLE_XSIZE_HIMETRIC cxSrc,//在源图像上水平拷贝的数量
2 j, x- E3 c h a OLE_YSIZE_HIMETRIC cySrc,//在源图像上垂直拷贝的数量1 p' Q7 e8 r6 B5 V4 p
LPCRECT prcWBounds //指向目标图元设备环境句柄的指针);
4 J# ]' X" K5 F% O% x* W 小结:到此为止,通过上述代码已经能够在程序的客户区内显示JPEG、GIF等标准的图像了,但对于有多帧图片(即有动画)的GIF格式的图像,目前还只能显示第一帧,如要完整的显示GIF 动画的全过程,还需要外部Active X控件的支持。 |