在RichEdit中插入Bitmap/GIF动画以及获取这些元素的信息的方法

来源:互联网 发布:经济学书籍推荐知乎 编辑:程序博客网 时间:2024/06/02 20:21

    利用RichEdit制作表情控件是,首先需要向RichEdit中插入图片(Bitmap)或GIF动画,然后需要从RichEdit中获取Bitmap/GIF的信息,以便向远端传送。

    本人对RichEdit了解很有限。下面是本人根据网上找到的资料,以通过看MSDN整理出来的实现在RichEdit中插入Bitmap与/GIF的方法,在这里共享给大家。RichEdit方面的高手不要取笑。

    1.在RichEdit中插入Bitmap/GIF的方法

        下面的代码是从网上找来的,我稍微作了一点修改(代码中红色部分是我改过的)。

ImageDataObect.h

====================================================

#ifndef IMAGE_DATA_OBJECT__H
#define IMAGE_DATA_OBJECT__H

#include <Richedit.h>
#include <objidl.h.>
#include <Richole.h>

class CImageDataObject : IDataObject
{
public:
    // This static fumction accepts those parameters:
    // IRichEditOle* : a pointer to IRochEditOle interface for the RichEdit Control
    // HBITMAP : the bitmap handle.
    //DWORD dwUser - 位图相关的信
    // After calling the function, it inserts the image in the current
    //    position of the RichEdit
    //
    static void InsertBitmap(IRichEditOle* pRichEditOle, HBITMAP hBitmap,DWORD dwUser);
    static void InsertGif(IRichEditOle *pRichEditOle,const char *gif_file,DWORD dwUser);

private:
    ULONG    m_ulRefCnt;
    BOOL    m_bRelease;

    // The data being bassed to the richedit
    //
    STGMEDIUM m_stgmed;
    FORMATETC m_fromat;

public:
    CImageDataObject() : m_ulRefCnt(0)
    {
        m_bRelease = FALSE;
    }

    ~CImageDataObject()
    {
        if (m_bRelease)
            ::ReleaseStgMedium(&m_stgmed);
    }

    // Methods of the IUnknown interface
    //
    STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
    {
        if (iid == IID_IUnknown || iid == IID_IDataObject)
        {
            *ppvObject = this;
            AddRef();
            return S_OK;
        }
        else
            return E_NOINTERFACE;
    }
    STDMETHOD_(ULONG, AddRef)(void)
    {
        m_ulRefCnt++;
        return m_ulRefCnt;
    }
    STDMETHOD_(ULONG, Release)(void)
    {
        if (--m_ulRefCnt == 0)
        {
            delete this;
        }

        return m_ulRefCnt;
    }

    // Methods of the IDataObject Interface
    //
    STDMETHOD(GetData)(FORMATETC *pformatetcIn, STGMEDIUM *pmedium) {
        HANDLE hDst;
        hDst = ::OleDuplicateData(m_stgmed.hBitmap, CF_BITMAP, NULL);
        if (hDst == NULL)
        {
            return E_HANDLE;
        }

        pmedium->tymed = TYMED_GDI;
        pmedium->hBitmap = (HBITMAP)hDst;
        pmedium->pUnkForRelease = NULL;

        return S_OK;
    }
   
    STDMETHOD(GetDataHere)(FORMATETC* pformatetc, STGMEDIUM*  pmedium )
    {
        return E_NOTIMPL;
    }
   
    STDMETHOD(QueryGetData)(FORMATETC*  pformatetc )
    {
        return E_NOTIMPL;
    }
   
    STDMETHOD(GetCanonicalFormatEtc)(FORMATETC*  pformatectIn ,FORMATETC* pformatetcOut )    
    {
        return E_NOTIMPL;
    }
   
    STDMETHOD(SetData)(FORMATETC* pformatetc , STGMEDIUM*  pmedium , BOOL  fRelease )
    {
        m_fromat = *pformatetc;
        m_stgmed = *pmedium;

        return S_OK;
    }
   
    STDMETHOD(EnumFormatEtc)(DWORD  dwDirection , IEnumFORMATETC**  ppenumFormatEtc )
    {
        return E_NOTIMPL;
    }
   
    STDMETHOD(DAdvise)(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink,
        DWORD *pdwConnection)
    {
        return E_NOTIMPL;
    }
   
    STDMETHOD(DUnadvise)(DWORD dwConnection)
    {
        return E_NOTIMPL;
    }
   
    STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppenumAdvise)
    {
        return E_NOTIMPL;
    }

    // Some Other helper functions
    //
    void SetBitmap(HBITMAP hBitmap);
    IOleObject *GetOleObject(IOleClientSite *pOleClientSite, IStorage *pStorage);
};

#endif // IMAGE_DATA_OBJECT__H

===========================

ImageDataObject.cpp

#include "stdafx.h"  //我很不喜欢这个头文件,这个程序只能在windows下运行,就留着吧
#include "ImageDataObject.h"

#import "ImageOle.dll" raw_interfaces_only, raw_native_types, no_namespace, named_guids, auto_search
static CLSID const gif_clsid = { 0x6ADA938, 0xFB0, 0x4BC0, { 0xB1, 0x9B, 0xA, 0x38, 0xAB, 0x17, 0xF1, 0x82 } };

void CImageDataObject::InsertBitmap(IRichEditOle* pRichEditOle, HBITMAP hBitmap,DWORD dwUser)
{
    SCODE sc;

    // Get the image data object
    //
    CImageDataObject *pods = new CImageDataObject;
    LPDATAOBJECT lpDataObject;

    pods->QueryInterface(IID_IDataObject, (void **)&lpDataObject);
    pods->SetBitmap(hBitmap);

    // Get the RichEdit container site
    //
    IOleClientSite *pOleClientSite;   
   
    pRichEditOle->GetClientSite(&pOleClientSite);
    // Initialize a Storage Object
    //
    IStorage *pStorage;   

    LPLOCKBYTES lpLockBytes = NULL;
    sc = ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);
   
    sc = ::StgCreateDocfileOnILockBytes(lpLockBytes,
        STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &pStorage);


    // The final ole object which will be inserted in the richedit control
    //
    IOleObject *pOleObject;
    pOleObject = pods->GetOleObject(pOleClientSite, pStorage);

    // all items are "contained" -- this makes our reference to this object
    //  weak -- which is needed for links to embedding silent update.
    OleSetContainedObject(pOleObject, TRUE);

    // Now Add the object to the RichEdit
    //
    REOBJECT reobject;
    ZeroMemory(&reobject, sizeof(REOBJECT));
    reobject.cbStruct = sizeof(REOBJECT);
   
    CLSID clsid;
    sc = pOleObject->GetUserClassID(&clsid);


    reobject.clsid = clsid;
    reobject.cp = REO_CP_SELECTION;
    reobject.dvaspect = DVASPECT_CONTENT;
    reobject.poleobj = pOleObject;
    reobject.polesite = pOleClientSite;
    reobject.pstg = pStorage;
 reobject.dwUser = dwUser;

    // Insert the bitmap at the current location in the richedit control
    //
    pRichEditOle->InsertObject(&reobject);

    // Release all unnecessary interfaces
    //
    pOleObject->Release();
    pOleClientSite->Release();
    pStorage->Release();
    lpDataObject->Release();
}

void CImageDataObject::InsertGif(IRichEditOle *lpRichEditOle,const char *gif_file,DWORD dwUser)
{
 LPOLEOBJECT  lpObject=NULL;
 LPSTORAGE       lpStorage=NULL;
 LPOLECLIENTSITE lpClientSite=NULL;
 LPLOCKBYTES  lpLockBytes = NULL;

 HRESULT hr=S_OK;
 CLSID clsid=CLSID_NULL;
 do{
  hr= ::CreateILockBytesOnHGlobal(NULL, TRUE, &lpLockBytes);
  if (hr != S_OK || lpLockBytes==NULL) 
   break;

  hr= ::StgCreateDocfileOnILockBytes(lpLockBytes, STGM_SHARE_EXCLUSIVE|STGM_CREATE|STGM_READWRITE, 0, &lpStorage);
  if (hr!= S_OK||lpStorage==NULL) 
   break;

  hr=lpRichEditOle->GetClientSite(&lpClientSite);
  if (hr!= S_OK||lpClientSite==NULL) 
   break;

  try
  {
   HRESULT hr;
   IGifAnimator *pGif  = NULL;
   hr = CoCreateInstance(gif_clsid,NULL,CLSCTX_INPROC_SERVER , IID_IGifAnimator,(void **)&pGif);
   if(FAILED(hr) || pGif == NULL)
    break ;

   _bstr_t bstrPath(gif_file);
   pGif->LoadFromFile(bstrPath);
   if(FAILED(hr))
   {
    pGif->Release();
    break ;
   }

   hr = pGif->QueryInterface(IID_IOleObject, (void**)&lpObject);
   if( FAILED(hr)||lpObject==NULL) 
   {
    pGif->Release();
    break ;
   }
   
   hr=OleSetContainedObject(lpObject, TRUE);
   if( FAILED(hr) )
   {
    pGif->Release();
    break ;
   }
   hr=lpObject->GetUserClassID(&clsid);
   if( FAILED(hr) )
   {
    pGif->Release();
    break ;
   }

   REOBJECT reobject;
   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.dwUser = dwUser;
   reobject.poleobj = lpObject;
   reobject.polesite = lpClientSite;
   reobject.pstg = lpStorage;
   SIZEL sizel={0,0};
   reobject.sizel = sizel;
   hr=lpRichEditOle->InsertObject(&reobject);
  }
  catch( _com_error &e )
  {
  }

 }while(FALSE);
 if(lpLockBytes) lpObject->Release(); 
 if(lpLockBytes) lpLockBytes->Release();
 if(lpClientSite) lpClientSite->Release();
 if(lpRichEditOle) lpRichEditOle->Release();
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

void CImageDataObject::SetBitmap(HBITMAP hBitmap)
{


    STGMEDIUM stgm;
    stgm.tymed = TYMED_GDI;                    // Storage medium = HBITMAP handle       
    stgm.hBitmap = hBitmap;
    stgm.pUnkForRelease = NULL;                // Use ReleaseStgMedium

    FORMATETC fm;
    fm.cfFormat = CF_BITMAP;                // Clipboard format = CF_BITMAP
    fm.ptd = NULL;                            // Target Device = Screen
    fm.dwAspect = DVASPECT_CONTENT;            // Level of detail = Full content
    fm.lindex = -1;                            // Index = Not applicaple
    fm.tymed = TYMED_GDI;                    // Storage medium = HBITMAP handle

    this->SetData(&fm, &stgm, TRUE);       
}

IOleObject *CImageDataObject::GetOleObject(IOleClientSite *pOleClientSite, IStorage *pStorage)
{


    SCODE sc;
    IOleObject *pOleObject;
    sc = ::OleCreateStaticFromData(this, IID_IOleObject, OLERENDER_FORMAT,
            &m_fromat, pOleClientSite, pStorage, (void **)&pOleObject);

    return pOleObject;
}

/////////////

  OK,下面是想RichEdit中插入bitmap的范例

  CImageDataObject::InsertBitmap(m_sendRichEdit.GetOleInterface(),bmp.m_hBitmap,dwBitmapInfo); 

  上面是m_sendRichEdit是一个RichEdit控件(这段代码是从一个WTL项目中提取出来的)。

  注意:上面的dwBitmapInfo就是应用程序设置的与插入RichEdit中的Bitmap相关的信息。

  2. 从EditRich中提取位图信息

     下面是范例代码,其中原来就不多说了,看代码吧。

    //获取RichEdit中有几个bitmap,这里假设RichEdit中有位图文件
    int c = m_sendRichEdit.GetOleInterface()->GetObjectCount();     

   for(int i = 0 ; i < c ; i++) //遍历位图
   {
       REOBJECT object;  //位图信息存在这里
     memset(&object,0,sizeof(REOBJECT));
     object.cbStruct = sizeof(REOBJECT);
     m_sendRichEdit.GetOleInterface()->GetObject(i,&object,REO_GETOBJ_ALL_INTERFACES);

     int pos = object.cp ; //位图的位置信息
     DWORD dwUSer  =object.dwUSer ; //位图的信息,之前应用程序设置的,应有程序当然知道什么意思了
  }

/////////////////////////////////////////////////////

OVER

////////////////////////////////////////////////////

原创粉丝点击