在RichEdit控件中插入OLE對象(ActiveX控件)

  有時候,我們需要在一個容器中插入各種不同的對象,比如,QQ聊天對話框裏可以插入各種靜態和動態的圖片,甚至還可以插入flash文件,這些都是通過OLE技術來實現的。OLE技術是基於COM的,而COM又是非常複雜的東西,想要學習COM得花很多的時間,《COM技術內幕》,《COM原理和應用》,《INSIDE OLE 2》都是非常好的學習COMOLE的書,但要把這些書啃完,弄懂,幾個月甚至半年都過去了。學習COM是一個鬱悶、漫長的過程,雖然進步很慢,但堅持下去會很有意思。如果我們僅僅是使用別人的組件,並將別人的組件插入到自己的容器中,也不是很複雜,下面就是一個例子。
  我們以MSDNATL Tutorial中創建的組件做爲我們要插入的對象(該組件的創建請看MSDN)。
1、創建一個COM客戶端基於對話框的工程,命名爲Client,按默認選項設置工程。

2、在主對話框中加入一個RichEdit控件,用ClassWizard爲添加一個表示該控件的變量,爲m_re,記住類型設爲control。爲主對話框加入一個按鈕,ID設爲IDC_INSERTPOLYGON,Caption設置爲InsertPolygon。
3、在CClientApp::InitInstance()函數中,在創建對話框的代碼前加入如下代碼:
if (AfxInitRichEdit() == FALSE)
 {
  return FALSE;
 }
如果不加入上面的代碼,應用程序將無法運行。
4、在Client.cpp中添加頭文件
#include "..//Polygon.h"  //DLL模塊頭文件
#include "..//Polygon_i.c" //接口定義
#include "Richole.h"
5、爲對話框類加入私有成員函數BOOL InsertPolygon(IRichEditOle* lpRichEditOle);將該函數定義如下:
BOOL CClientDlg::InsertPolygon(IRichEditOle* lpRichEditOle)
{
 IStorage*  lpStorage  = NULL;//
存儲接口
 IOleObject*  lpOleObject  = NULL;//OLE
對象
 LPLOCKBYTES  lpLockBytes  = NULL;//LOCKBYTE
 IOleClientSite* lpOleClientSite = NULL; 
 IPolyCtl*       lpPolyCtl = NULL;    //
控件
 CLSID   clsid;
 REOBJECT  reobject;
 HRESULT   hr;


 if(lpRichEditOle == NULL)
  return FALSE;
 //
創建PolyCtl對象並獲取接口
 hr = ::CoCreateInstance(CLSID_PolyCtl,NULL,CLSCTX_INPROC,IID_IPolyCtl,(LPVOID*)&lpPolyCtl);
 if( lpPolyCtl == NULL )
 {
  return FALSE;
 }
 
// USES_CONVERSION;
 BOOL bRet = TRUE;
 
 try{
  hr = lpPolyCtl->QueryInterface(&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;

  hr = lpRichEditOle->InsertObject( &reobject );
  if (hr != S_OK)
   AfxThrowOleException(hr);
  OleSetContainedObject(lpOleObject,TRUE);
 }

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

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

 return bRet;
}
6、爲InsertPolygon按鈕添加響應函數,定義如下:
void CClientDlg::OnInsertpolygon()
{
 IRichEditOle* lpRichEditOle = NULL;
 lpRichEditOle = m_re.GetIRichEditOle();
 if (lpRichEditOle != NULL)
 {
  InsertPolygon(lpRichEditOle);
  lpRichEditOle->Release();
 }
}
7、運行效果圖如下:


  如果你有自己的控件,可以按上述的方法插入。

發佈了29 篇原創文章 · 獲贊 0 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章