Fav*_*ius 10 internet-explorer activex bho atl ieaddon
我试图从javascript调用我的BHO方法.问题与以下帖子中说明的相同:
第三个链接是另一个SO帖子谈论它,但我不理解需求和代码.此外,共享工作样本使用ie 8和windows vista(即7)保持崩溃.
如果它有助于我的BHO使用ATL用C++编写.
我尝试过的:
我写了一个非常基本的BHO,并试图为所提到的方法在这里由伊戈尔Tandetnik.没有生成异常但是当我在IE中打开以下html文件时它会说对象未定义.
<html>
<head>
<script language='javascript'>
function call_external(){
try{
alert(window.external.TestScript);
//JQueryTest.HelloJquery('a');
}catch(err){
alert(err.description );
}
}
</script>
</head>
<body id='bodyid' onload="call_external();">
<center><div><span>Hello jQuery!!</span></div></center>
</boay>
</html>
Run Code Online (Sandbox Code Playgroud)
题:
window.external但上面链接[2]使用的方式var x = new ActiveXObject("MySampleATL.MyClass");; 调用约定是相同还是不同?注意:
[id(1), helpstring("method DoSomething")] HRESULT DoSomething();在BHO IDL文件中插入它来实现.我不确定它是如何完成的,并且无法通过谷歌找到任何支持资源.编辑1
window.external.检查一下.特别是标题为IDocHostUIHandler::GetExternal: Extending the DOM.Now的假设我们的IDispatch接口位于实现IDocHostUIHandler的同一对象上.然后我们可以这样做:
HRESULT CBrowserHost::GetExternal(IDispatch **ppDispatch)
{
*ppDispatch = this;
return S_OK;
}
Run Code Online (Sandbox Code Playgroud)
这种方法的问题在于它不会附加到现有的Windows方法,而是替换它们.请告诉我是不是错了.
编辑2
The BHO Class:
class ATL_NO_VTABLE CTestScript :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CTestScript, &CLSID_TestScript>,
public IObjectWithSiteImpl<CTestScript>,
public IDispatchImpl<ITestScript, &IID_ITestScript, &LIBID_TestBHOLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
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<IWebBrowser2> m_spWebBrowser;
BOOL m_fAdvised;
};
Run Code Online (Sandbox Code Playgroud)
// TestScript.cpp : Implementation of 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<CTestScript>::SetSite(pUnkSite);
}
void STDMETHODCALLTYPE CTestScript::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)
{
CComPtr<IDispatch> dispDoc;
CComPtr<IHTMLDocument2> ifDoc;
CComPtr<IHTMLWindow2> ifWnd;
CComPtr<IDispatchEx> 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 );
}
Run Code Online (Sandbox Code Playgroud)
The Javascript:
<script language='javascript'>
function call_external(){
try{
alert(window.ITestScript);
}catch(err){
alert(err.description );
}
}
</script>
Run Code Online (Sandbox Code Playgroud)
编辑3
I will also suggest you to see the MSDN IDispatcEx sample.如果您找到解决方案,请发帖,如果我找到解决方案,那么我肯定会在这里更新.
编辑4
See my last comment in URI's post. Issue Resolved.
Igor Tandetnik的方法是正确的方法.该帖子的问题是示例代码(至少在我发现它的几页上)是不完整的.我有很多试验和错误,直到我开始工作.这是我的代码的很大一部分,可以解决这个问题:
假设您有一个类CMyBho,并且您希望为Java脚本公开IMyBho自动化对象
类定义:
您从标准CComObjectRootEx和CComCoClass派生,使其"共同创建".您有IObjectWithSiteImpl(重用此基类实现的m_spUnkSite).IDispatchImpl实现您的自动化对象,IDispatchEventImpl是从浏览器获取通知的接收器:
class ATL_NO_VTABLE CMyBho
: public CComObjectRootEx<CComSingleThreadModel>
, public CComCoClass<CMyBho, &CLSID_MyBho>
, public IObjectWithSiteImpl<CMyBho>
, public IDispatchImpl<IMyBho, &IID_IMyBho, &LIBID_MyBhoLib, 1, 0>
, IDispatchEventImpl<1, CMyBho, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>
{
...
public:
BEGIN_COM_MAP(CMyBho)
COM_INTERFACE_ENTRY(IMyBho)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IObjectWithSite)
END_COM_MAP()
...
BEGIN_SINK_MAP(CMyBho)
SINK_ENTRY_EX( 1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocComplete )
END_SINK_MAP()
...
private:
CComPtr<IWebBrowser2> m_ifbrz; // pointer to the hosting browser
}
Run Code Online (Sandbox Code Playgroud)
接下来,在SetSite方法中,您注册以获取通知.不要忘记调用基类.
STDMETHODIMP CMyBho::SetSite( IUnknown* unkSite )
{
...
hr = IObjectWithSiteImpl::SetSite( unkSite );
if( unkSite ) {
...
// advise to browser event.
CComPtr<IServiceProvider> ifsp;
hr = m_spUnkSite.QueryInterface( &ifsp );
hr = ifsp->QueryService( SID_SwebBrowserApp, IID_IWebBrowser2, &m_ifbrz );
hr = DispEventAdvise( m_ifbrz );
}
else {
// release various resources (m_ifbrz will be released automatically by its dtor)
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
文档加载完成后,将调用此函数:
void STDMETHODCALLTYPE CMyBho::onDocComplete( IDispatch* dispBrz, VARIANT* pvarUrl )
{
CComPtr<IDispatch> dispDoc;
CComPtr<IHTMLDocument2> ifDoc;
CComPtr<IHTMLWindow2> ifWnd;
CComPtr<IDispatchEx> dispxWnd;
hr = m_ifbrz->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_PROPERTYPUTREF,
¶ms, NULL, NULL, NULL );
}
Run Code Online (Sandbox Code Playgroud)
至于你的其他问题:
显然,我的回答意味着您可以从BHO创建一个自动化对象来编写脚本.您的对象也可以使用新的ActiveXObject进行实例化.在这种情况下,不要忘记告诉IE你的对象是安全的脚本(旁注:让您的BHO安全的脚本.确保恶意网站将无法利用您的BHO).
我认为window.myBho比window.external.myBho更好.从语义上讲,"外部"是指mshtml浏览器控件托管在另一个应用程序中.
希望这有帮助.
| 归档时间: |
|
| 查看次数: |
6675 次 |
| 最近记录: |