在richedit中插入OLE控件时的问题

mgtcllxl 2008-10-29 11:08:56
自己写了一个wndless的ATL控件,在richedit中插入后可正常显示,但是m_spClientSite为空,请问如何获得一个合法的IOleClientSite
...全文
300 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
wndrfll 2008-12-03
  • 打赏
  • 举报
回复
呵呵呵,和你遇到同样的问题,我是这样获取IWebBrowser2的。

control的头文件中定义成员变量:
CComPtr<IWebBrowser2> m_spWebBrowser;
DWORD m_dwCookie;

然后重载IOleObjectImpl的SetClientSite函数,注意第一行代码:
其实你可以看看IOleObjectImpl的SetClientSite函数默认不重载的代码实现,其中只是调用了控件的IOleObject_SetClientSite函数而已,而IOleObject_SetClientSite函数实际上是CComControlBase的一个成员函数,既然是控件,应该第一个父类就是CComControlBase吧,所以这样绕来绕去得到了IWebBrowser2,你可以试试不重载这个函数,然后在IOleObjectImpl的SetClientSite的代码中设置断点,可以发现只要控件被加载就会执行SetClientSite函数。这里我们重载后,加入自己的代码,把IWebBrowser2保存下来供日后使用。
希望能帮到你。。。

STDMETHOD(SetClientSite)( IOleClientSite* pClientSite )
{
HRESULT hr = IOleObject_SetClientSite(pClientSite); // 注意这一行
if (!pClientSite)
{
return hr;
}

CComPtr<IOleContainer> spContainer;
m_spClientSite->GetContainer(&spContainer);
ATLASSERT(spContainer);
if (SUCCEEDED(hr))
{
// Set up the event sink.
//
CComQIPtr<IServiceProvider, &IID_IServiceProvider>
spServiceProvider(spContainer);
ATLASSERT(spServiceProvider);
if (spServiceProvider)
{
spServiceProvider->QueryService(SID_SInternetExplorer,
IID_IWebBrowser2,
(void**)&m_spWebBrowser);
ATLASSERT(m_spWebBrowser);

if (m_spWebBrowser)
{
AtlAdvise(m_spWebBrowser, GetUnknown(),
DIID_DWebBrowserEvents2, &m_dwCookie);
}
}
}
return hr;
}
mgtcllxl 2008-10-31
  • 打赏
  • 举报
回复
顶啊
mgtcllxl 2008-10-30
  • 打赏
  • 举报
回复
to:VsirSoft
现在的问题就是找不到合适的IOleClientSite来SetClientSite
to:jameshooo
是不是要在控件中重写SetClientSite来保存IOleClientSite?

我是直接通过接口来获取IOleObject的,控件本身未激活,调用InPlaceActive时会由于m_spClientSite为空而返回
mgtcllxl 2008-10-30
  • 打赏
  • 举报
回复
现在SetClientSite这个方法我重写了,但是还是没有合适的IOleClientSite 来进行设置,如果使用IRichEditOle的IOleClientSite 的话在OnInPlaceActivate的时候程序会抛出异常,我应该从哪个容器中获取IOleClientSite 呢?
jameshooo 2008-10-30
  • 打赏
  • 举报
回复
看起来问题是当你想要site时SetClientSite还未被执行过。直接从容器中获取site吧,激活也是调用容器方法。
jameshooo 2008-10-30
  • 打赏
  • 举报
回复
你的控件是不是从IOleObjectImpl<>继承的?如果是,你看看它的SetClientSite代码:
STDMETHOD(SetClientSite)(IOleClientSite *pClientSite)
{
T* pT = static_cast<T*>(this);
ATLTRACE(atlTraceControls,2,_T("IOleObjectImpl::SetClientSite\n"));
return pT->IOleObject_SetClientSite(pClientSite);
}

在你的控件中实现IOleObject_SetClientSite这个函数,然后自己保存参数。
yeah920 2008-10-30
  • 打赏
  • 举报
回复
帮忙顶一下.
mgtcllxl 2008-10-30
  • 打赏
  • 举报
回复
顶下
jameshooo 2008-10-29
  • 打赏
  • 举报
回复
不可能吧,插入控件时容器会调用控件的SetClientSite来告诉你IOleClientSite的,你应该保存起来。
VsirSoft 2008-10-29
  • 打赏
  • 举报
回复
看来是与包容器没有创建联系。

调用SetClientSite来初始化

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧