Я пытаюсь вызвать свой метод BHO из javascript. Проблема такая же, как указано в следующих сообщениях:
Третья ссылка - это еще одно сообщение SO, в котором говорится об этом, но я не понимал необходимости и кода. Также общий рабочий образец продолжает давать сбой в Windows 7 с IE 8 и Windows Vista с IE 7.
Если это помогает, мой BHO написан на C ++ с использованием ATL.
Что я пробовал:
Я написал очень простой BHO и попробовал подход, упомянутый здесь Игорем Тандетником . Никакого исключения не создается, но когда я открываю следующий html-файл в IE, он говорит object undefined .
Hello jQuery!!
Вопрос:
window.external
, но способ, показанный в приведенной выше ссылке [2] , использует var x = new ActiveXObject ("MySampleATL.MyClass ");
; Оба соглашения о вызовах одинаковы или различны? Примечание:
[id (1 ), helpstring ("method DoSomething")] HRESULT DoSomething ();
в IDL-файле BHO. Я не уверен, как это было сделано, и не смог найти какой-либо вспомогательный ресурс через Google. Редактировать 1
Кажется, есть способ расширить window.external
. Отметьте это . В частности, раздел под названием IDocHostUIHandler::GetExternal: Extending the DOM.
Теперь предположим, что наш интерфейс IDispatch находится на тот же объект, который реализует IDocHostUIHandler. Тогда мы можем сделать что-то вроде этого:
HRESULT CBrowserHost::GetExternal(IDispatch **ppDispatch)
{
*ppDispatch = this;
return S_OK;
}
Проблема этого подхода заключается в том, что он не добавляется к существующим методам Windows, а скорее заменяет их. Скажите, пожалуйста, если я ошибаюсь.
Редактировать 2
Класс BHO:
class ATL_NO_VTABLE CTestScript :
public CComObjectRootEx,
public CComCoClass,
public IObjectWithSiteImpl,
public IDispatchImpl,
public IDispEventImpl<1, CTestScript, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>
{
public:
CTestScript()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_TESTSCRIPT)
DECLARE_NOT_AGGREGATABLE(CTestScript)
BEGIN_COM_MAP(CTestScript)
COM_INTERFACE_ENTRY(ITestScript)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IObjectWithSite)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public:
BEGIN_SINK_MAP(CTestScript)
SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
//SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_NAVIGATECOMPLETE2, OnNavigationComplete)
END_SINK_MAP()
void STDMETHODCALLTYPE OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL);
//void STDMETHODCALLTYPE OnNavigationComplete(IDispatch *pDisp, VARIANT *pvarURL);
STDMETHOD(SetSite)(IUnknown *pUnkSite);
HRESULT STDMETHODCALLTYPE DoSomething(){
::MessageBox(NULL, L"Hello", L"World", MB_OK);
return S_OK;
}
public:
//private:
// InstallBHOMethod();
private:
CComPtr m_spWebBrowser;
BOOL m_fAdvised;
};
// TestScript.cpp: Реализация CTestScript
#include "stdafx.h"
#include "TestScript.h"
// CTestScript
STDMETHODIMP CTestScript::SetSite(IUnknown* pUnkSite)
{
if (pUnkSite != NULL)
{
HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser);
if (SUCCEEDED(hr))
{
hr = DispEventAdvise(m_spWebBrowser);
if (SUCCEEDED(hr))
{
m_fAdvised = TRUE;
}
}
}else
{
if (m_fAdvised)
{
DispEventUnadvise(m_spWebBrowser);
m_fAdvised = FALSE;
}
m_spWebBrowser.Release();
}
return IObjectWithSiteImpl::SetSite(pUnkSite);
}
void STDMETHODCALLTYPE CTestScript::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)
{
CComPtr dispDoc;
CComPtr ifDoc;
CComPtr ifWnd;
CComPtr dispxWnd;
HRESULT hr = m_spWebBrowser->get_Document( &dispDoc );
hr = dispDoc.QueryInterface( &ifDoc );
hr = ifDoc->get_parentWindow( &ifWnd );
hr = ifWnd.QueryInterface( &dispxWnd );
// now ... be careful. Do exactly as described here. Very easy to make mistakes
CComBSTR propName( L"myBho" );
DISPID dispid;
hr = dispxWnd->GetDispID( propName, fdexNameEnsure, &dispid );
CComVariant varMyBho( (IDispatch*)this );
DISPPARAMS params;
params.cArgs = 1;
params.cNamedArgs = 0;
params.rgvarg = &varMyBho;
params.rgdispidNamedArgs = NULL;
hr = dispxWnd->Invoke( dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT,
¶ms, NULL, NULL, NULL );
}
Javascript:
Редактировать 3
Потратив на это три дня, я думаю, что мне следует взять путь ActiveX. Написание базового ActiveX - это просто способ сделать его простым, написанным и протестированным на всех основных выпусках IE. Я оставляю этот вопрос открытым, см. Комментарии в ответе Ури (большое ему спасибо). Я испробовал большинство его предложений (кроме 4 и 5). I will also suggest you to see the MSDN IDispatcEx sample
. Если вы найдете решение, напишите, если я найду решение, я обязательно обновлю его здесь.
Редактировать 4
См. Мой последний комментарий в сообщении URI. Проблема решена.