美好的一天,我对于Internet Explorer的浏览器帮助器对象有问题。我需要从页面中注入的js代码中调用我的c ++代码,因此我必须将一些c ++方法导出到js代码中。我已经通过IDispatchEx::Invoke
找到了方法,但是这种方法在某些站点上经常失败。
void __stdcall CEventSink::DocumentComplete(IDispatch *pObject, VARIANT *pvarUrl)
{
if(pObject)
{
IServiceProvider *pSp = NULL;
if(SUCCEEDED(pObject->QueryInterface(IID_IServiceProvider, (void**)&pSp)))
{
IWebBrowser2 *browser = NULL;
if(SUCCEEDED(pObject->QueryInterface(IID_IWebBrowser2, (void**)&browser)))
{
IDispatch *disp = NULL;
if(SUCCEEDED(browser->get_Document(&disp)))
{
IHTMLDocument2 *doc = NULL;
if(SUCCEEDED(disp->QueryInterface(IID_IHTMLDocument2, (void**)&doc)))
{
IHTMLWindow2 *w = NULL;
if(SUCCEEDED(doc->get_parentWindow(&w)))
{
CComPtr<IDispatchEx> dispxWnd;
if(local_data.tabs[(ptr_type)browser].bho)
{
if(SUCCEEDED(w->QueryInterface( &dispxWnd )))
{
CComBSTR propName( L"cbx" );
DISPID dispid;
if(SUCCEEDED ( dispxWnd->GetDispID( propName, fdexNameEnsure, &dispid )))
{
CComVariant varMyBho( (IDispatch*)local_data.tabs[(ptr_type)browser].bho );
DISPID dummy[] = {DISPID_PROPERTYPUT};
DISPPARAMS params;
params.cArgs = 1;
params.cNamedArgs = 0;
params.rgvarg = &varMyBho;
params.rgdispidNamedArgs = NULL;
if(FAILED( dispxWnd->Invoke( dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, ¶ms, NULL, NULL, NULL )))
{
MessageBoxA(NULL, "failed to dispxWnd->Invoke", "", MB_OK);
//TODO: handle error
}
}
呼叫
if(FAILED( dispxWnd->Invoke( dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, ¶ms, NULL, NULL, NULL )))
失败,但仅对于某些站点,例如tee-links.com。 local_data.tabs[(ptr_type)browser].bho
存储指向具有已实现接口的类的实例的指针。正如第一个评论所建议的,添加了一些代码来检索有关错误的信息,快速而又肮脏HRESULT hr = dispxWnd->Invoke( dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, ¶ms, NULL, NULL, NULL );
if(FAILED(hr))
{
_com_error err(hr);
LPCTSTR msg = err.ErrorMessage();
char errnum[32];
_snprintf(errnum, 31, "%x", hr);
MessageBox(NULL, msg, to_utf16(errnum).c_str(), MB_OK);
因此,我们收到了类似“未找到组成员”的错误消息,我安装了俄罗斯操作系统,因此无法准确地说出错误代码80020003
最佳答案
您将获得一个带有IDispatchEx::GetDispID
的动态DISPID,它应该与IDispatchEx::InvokeEx
一起使用,但是随后将其提供给IDispatch::Invoke
,它应该与IDIspatch::GetIDsOfNames
返回的静态DISPID一起使用。
PS:我也发现以下几行很有趣:
CComVariant varMyBho( (IDispatch*)local_data.tabs[(ptr_type)browser].bho );
这些真的是所有
IDispatch
指针吗?还是它们是IUnknown
指针?如果是后者,则必须QueryInterface
。