您的位置:首页 > 其它

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

2005-02-01 12:44 274 查看
  有时候,我们需要在一个容器中插入各种不同的对象,比如,QQ聊天对话框里可以插入各种静态和动态的图片,甚至还可以插入flash文件,这些都是通过OLE技术来实现的。OLE技术是基于COM的,而COM又是非常复杂的东西,想要学习COM得花很多的时间,《COM技术内幕》,《COM原理和应用》,《INSIDE OLE 2》都是非常好的学习COM和OLE的书,但要把这些书啃完,弄懂,几个月甚至半年都过去了。学习COM是一个郁闷、漫长的过程,虽然进步很慢,但坚持下去会很有意思。如果我们仅仅是使用别人的组件,并将别人的组件插入到自己的容器中,也不是很复杂,下面就是一个例子。
  我们以MSDN的ATL 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、运行效果图如下:

  如果你有自己的控件,可以按上述的方法插入。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息