现在的位置: 首页 > 综合 > 正文

一个可以显示图片(包括GIF动画)的ATL控件,以及在RichEdit中如何使用此控件插入图片

2013年10月11日 ⁄ 综合 ⁄ 共 3167字 ⁄ 字号 评论关闭

给大家提供一个可以显示图片(包括GIF动画)的ATL控件,以及在RichEdit中如何使用此控件插入图片。其实自己没做什么,主要是参考了Oleg Bykov的文档,只是把他的代码加进ATL工程中封装成了一个ATL控件,原文地址在:http://www.codeproject.com/KB/graphics/pictureex.aspx
最直接的办法是您下载已经编译好的文件,您下载MaiYuanOleImg.zip然后解压缩,运行解压缩后目录下Reg.bat就可以直接使用此控件了。点击下载
如果您需要对此控件作修改,可以下载此控件的源代码。点击下载
源代码的一点说明,MYOleImage.h和MYOleImage.cpp中的CMYOleImage类用来显示图像和GIF动画。对这个类,绝大部分的代码是从Oleg Bykov的CPictureExWnd这个类Copy而来。
修改的地方主要在OnDraw(ATL_DRAWINFO& di)这个成员函数中。GIF的动画是采用开线程的方式,我想,如果您需要显示几百上千的GIF动画,那会把您的电脑跑得很慢。
自己添加了一个函数Load(BSTR),调用此函数将设置控件要显示的图像。
其他还有小的修改,请参照源代码

然后介绍在RichEdit中使用此控件插入图片(包括GIF动画), 采用在RichEdit中插入COM对象的方式插入此控件,这里只需要知道此控件对象的CLSID为:CLSID_MYOleImage,以及接口的IID为:IID_IMaiYuanOleImage。调用控件的成员函数Load就可以把图片加载到控件中显示。然后就能显示在RichEdit中了。
  TCHAR Filter[]=_T("JGP文件(*.jpg)|*.jpg;*.jpeg|GIF文件(*.gif)|*.gif|BMP文件(*.bmp)|*.bmp|所有文件(*.*)|*.*||");
    CFileDialog dlgOpen(TRUE,0,0,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,(LPCTSTR)Filter,NULL);
    if(dlgOpen.DoModal()==IDOK)
    {
  IRichEditOle* lpRichEditOle = m_RichEdit.GetIRichEditOle(); //m_RichEdit为您的RichEdit对象

  IStorage*  lpStorage  = NULL;//存储接口
  IOleObject*  lpOleObject  = NULL;//OLE对象
  LPLOCKBYTES  lpLockBytes  = NULL;//LOCKBYTE
  IOleClientSite* lpOleClientSite = NULL;
  CComPtr<IMaiYuanOleImage> IPic;
  CLSID   clsid;
  REOBJECT  reobject;
  HRESULT   hr;

  if(lpRichEditOle == NULL)
   return;
  //创建IMaiYuanOleImage对象并获取接口
  hr = ::CoCreateInstance(CLSID_MYOleImage,NULL,CLSCTX_INPROC,IID_IMaiYuanOleImage,(LPVOID*)&IPic);
  if( IPic == NULL )
  {
   return;
  }

  BOOL bRet = TRUE;

  try{
   hr = IPic->QueryInterface(IID_IOleObject, (void**)&lpOleObject);//获得数据对象接口
   if( hr != S_OK )
    AfxThrowOleException(hr);
   hr = lpOleObject->GetUserClassID(&clsid);
   if ( hr != S_OK)
    AfxThrowOleException(hr);

   hr = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);//创建LOCKBYTE对象
   if (hr != S_OK)
    AfxThrowOleException(hr);
   ASSERT(lpLockBytes != NULL);

   hr = ::StgCreateDocfileOnILockBytes(lpLockBytes,//创建复合文档
    STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &lpStorage);
   if (hr != S_OK)
   {
    VERIFY(lpLockBytes->Release() == 0);
    lpLockBytes = NULL;
    AfxThrowOleException(hr);
   }

   lpRichEditOle->GetClientSite(&lpOleClientSite);

   ZeroMemory(&reobject, sizeof(REOBJECT));//初始化一个对象 
   reobject.cbStruct = sizeof(REOBJECT);
   reobject.clsid  = clsid;
   reobject.cp   = REO_CP_SELECTION;
   reobject.dvaspect = DVASPECT_CONTENT;
   reobject.dwFlags = REO_BELOWBASELINE;
   reobject.poleobj = lpOleObject;
   reobject.polesite = lpOleClientSite;
   reobject.pstg  = lpStorage;

   lpOleObject->SetClientSite(lpOleClientSite);//
   hr = lpRichEditOle->InsertObject( &reobject );
   if (hr != S_OK)
    AfxThrowOleException(hr);
   OleSetContainedObject(lpOleObject,TRUE);
   IPic->Load(_bstr_t(dlgOpen.GetPathName())); //装载要显示的图像
  }

  catch( COleException* e )
  {
   TRACE(_T("OleException code:%d"),e->m_sc);
   e->Delete();
   bRet = FALSE;
  }

  // release the interface
  //if( IPic     != NULL )  IPic->Release();
  if( lpOleObject  != NULL )  lpOleObject->Release();
  if( lpOleClientSite != NULL ) lpOleClientSite->Release();
  if( lpStorage  != NULL ) lpStorage->Release();

  lpRichEditOle->Release();
 }
 
这里是使用测试的例子,点击下载

 

 

原来我打算在自己的IM软件中使用RichEdit作为输入框,所以写了这个控件,但是后来决定不使用RichEdit了,就没有再继续完善了。

因为这里显示图片用的是IPicture接口,所以.png图片是无法显示的。

如果需要显示更多的图片,推荐修改此控件的源代码,使用GDI+来显示图片。

如果我以后有时间,我用GDI+来重新实现

抱歉!评论已关闭.