我编写了一个IDocHostUIHandler的实现,以便为JavaScript提供嵌入式IE11控件的外部对象。一个类提供IUnknown,IDispatch和IDocHostUIHandler的实现。 IDispatch接口作为外部对象返回到GetExternal。 所有对IDocHostUIHandler的调用除GetExternal调用之外都调用原始处理程序。
例如,HideUI实现为:
HRESULT STDMETHODCALLTYPE mtQtWebBrowserDocHandler::HideUI(void)
{
qDebug("Calling HideUI");
if(m_defaultDocHostUIHandler)
{
HRESULT hr = m_defaultDocHostUIHandler->HideUI();
qDebug("Called HideUI");
return hr;
}
return E_NOTIMPL;
}
除了GetExternal之外的所有其他方法使用相同的模式:
HRESULT STDMETHODCALLTYPE mtQtWebBrowserDocHandler::GetExternal(IDispatch **ppDispatch)
{
qDebug("Calling GetExternal");
*ppDispatch = (IDispatch*)this;
return S_OK;
}
在JavaScript中,我执行以下操作:
var r1 = window.external.Test1();
这导致以下调试输出尾部:
'2016-10-10 11:09:19' DEBUG Calling GetHostInfo
'2016-10-10 11:09:19' DEBUG Called GetHostInfo
'2016-10-10 11:09:19' DEBUG mtQtWebBrowserDocHandler Release (ref now = 2)
'2016-10-10 11:09:19' DEBUG mtQtWebBrowserDocHandler AddRef (ref now = 3)
'2016-10-10 11:09:19' DEBUG Calling GetHostInfo
'2016-10-10 11:09:19' DEBUG Called GetHostInfo
'2016-10-10 11:09:19' DEBUG mtQtWebBrowserDocHandler Release (ref now = 2)
'2016-10-10 11:09:19' DEBUG Calling GetExternal
'2016-10-10 11:09:21' DEBUG mtQtWebBrowserDocHandler - IDispatch requested
'2016-10-10 11:09:21' DEBUG mtQtWebBrowserDocHandler AddRef (ref now = 3)
'2016-10-10 11:09:21' DEBUG mtQtWebBrowserDocHandler Release (ref now = 2)
'2016-10-10 11:09:21' DEBUG Calling ShowUI
'2016-10-10 11:09:21' DEBUG Called ShowUI
'2016-10-10 11:09:21' DEBUG Calling HideUI
'2016-10-10 11:09:21' DEBUG Called HideUI
HideUI的最终返回会导致INT 29h错误,ecx = FAST_FAIL_INCORRECT_STACK。预期的堆栈为0x18D9C4,实际堆栈为0x18D9A4,差异为0x20。
我完全神秘化了。对我的界面的其他调用正常工作,如果我只是从我的HideUI实现返回E_NOTIMPL,它没有任何区别。什么可能会使堆栈失去平衡?
答案 0 :(得分:2)
在GetExternal
函数中,您将返回一个接口指针,而不会增加引用计数,这将导致引用计数不匹配。更好的实施方式是:
HRESULT STDMETHODCALLTYPE mtQtWebBrowserDocHandler::GetExternal(IDispatch **ppDispatch)
{
qDebug("Calling GetExternal");
*ppDispatch = (IDispatch*)this;
this->AddRef();
return S_OK;
}
或在那里使用QueryInterface
。如果这是ATL,InternalQueryInterface
。我怀疑这是导致错误的原因,因为您引用的对象可能因Release
次AddRef
次调用而被销毁。
答案 1 :(得分:0)
答案似乎是当我在WebBrowser控件托管mshtml时,我在浏览器文档中使用了ICustomDoc。这显然不是一个好主意!相反,您应该使用WebBrowser控件提供的现有站点。我找到了一个在这里https://github.com/FastSpring/FsprgEmbeddedStoreWinMFC实现IDocHostUI的正确方法的例子,它非常有帮助。