gpt4 book ai didi

events - ATL C++ BHO 中的 Javascript 发布消息事件处理程序

转载 作者:行者123 更新时间:2023-12-01 22:15:47 25 4
gpt4 key购买 nike

在网页上,我有一个带有 JavaScript 发布消息的按钮。在我的 BHO IE 附加组件中,我需要一个用于此消息事件的事件监听器。有什么线索可以做到这一点吗?我的 OnDocumentComplete 如下。您能否提供更多指示,让我们可以编写处理此事件的代码。我想从此消息处理程序进行 REST API 调用。

TestScript.h:

// TestScript.h : Declaration of the CTestScript

#pragma once
#include "resource.h" // main symbols
#include "TestBHO_i.h"
#include <mshtml.h> // DOM interfaces

#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif

// CTestScript

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 IPersistPropertyBagImpl<CTestScript>,
public IObjectSafetyImpl<CTestScript, INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA>
{
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:
void EnableOpenOnDesktopButton(IHTMLDocument2 *pDocument);

private:
void AddPostMessage(IHTMLDocument2 *pDocument);

private:
CComPtr<IWebBrowser2> m_spWebBrowser;
BOOL m_fAdvised;
};

OBJECT_ENTRY_AUTO(__uuidof(TestScript), CTestScript)

测试脚本.cpp:

// TestScript.cpp : Implementation of CTestScript

#include "stdafx.h"
#include "TestScript.h"

// CTestScript

void debug(LPWSTR msg)
{
::MessageBox(NULL,msg,L"Debug",MB_OK);;
}

STDMETHODIMP CTestScript::SetSite(IUnknown* pUnkSite)
{
if (pUnkSite != NULL)
{
// Cache the pointer to IWebBrowser2.
HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser);
if (SUCCEEDED(hr))
{
// Register to sink events from DWebBrowserEvents2.
hr = DispEventAdvise(m_spWebBrowser);
if (SUCCEEDED(hr))
{
m_fAdvised = TRUE;
}
}
}
else
{
// Unregister event sink.
if (m_fAdvised)
{
DispEventUnadvise(m_spWebBrowser);
m_fAdvised = FALSE;
}

// Release cached pointers and other resources here.
m_spWebBrowser.Release();
}

// Call base class implementation.
return IObjectWithSiteImpl<CTestScript>::SetSite(pUnkSite);
}

void STDMETHODCALLTYPE CTestScript::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)
{
HRESULT hr = S_OK;

// Query for the IWebBrowser2 interface.
CComQIPtr<IWebBrowser2> spTempWebBrowser = pDisp;
//CComPtr<IEventTarget> spIEventTarget;
// Is this event associated with the top-level browser?
if (spTempWebBrowser && m_spWebBrowser &&
m_spWebBrowser.IsEqualObject(spTempWebBrowser))
{
// Get the current document object from browser...
CComPtr<IDispatch> spDispDoc;
hr = m_spWebBrowser->get_Document(&spDispDoc);
if (SUCCEEDED(hr))
{
// ...and query for an HTML document.
CComQIPtr<IHTMLDocument2> spHTMLDoc = spDispDoc;
if (spHTMLDoc != NULL)
{
EnableOpenOnDesktopButton(spHTMLDoc);
AddPostMessage(spHTMLDoc) ;
}
}
}
}


void CTestScript::EnableOpenOnDesktopButton(IHTMLDocument2* pDocument)
{
CComPtr<IHTMLElement> bodypt;
CComPtr<IHTMLElement> html;
pDocument->get_body(&bodypt);
bodypt->get_parentElement(&html);
//TODO: concatinate old class and new class and apply toht
BSTR className = L" my-browser-extension";
html->put_className(className);
}


void CTestScript::AddPostMessage(IHTMLDocument2* pDocument)
{
HRESULT hr = S_OK;
CComPtr<IHTMLWindow2> _spWindow;
hr = pDocument->get_parentWindow(reinterpret_cast<IHTMLWindow2 **>(&_spWindow));
if (SUCCEEDED(hr) && _spWindow)
{
CComPtr<IEventTarget> spIEventTarget;
hr = _spWindow->QueryInterface(IID_IEventTarget, reinterpret_cast<void **>(&spIEventTarget));
if (SUCCEEDED(hr) && spIEventTarget)
{
_pIEUIEventListener = new CIEUIEventListener(); // This class derives from IDispatch
hr = spIEventTarget->addEventListener(_bstr_t("message"), _pIEUIEventListener, VARIANT_TRUE);
if (SUCCEEDED(hr))
{
debug(L"HEREE");
}
}
}
}

IEUIEventListener.h:

#pragma once

class CIEUIEventListener : public IDispatchEx
{
public:
CIEUIEventListener(void);
~CIEUIEventListener(void);

HRESULT STDMETHODCALLTYPE Invoke(
DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS *pDispParams,
VARIANT *pVarResult,
EXCEPINFO *pExcepInfo,
UINT *puArgErr);
};

IEUIEventListener.cpp:

#include "StdAfx.h"
#include "IEUIEventListener.h"

CIEUIEventListener::CIEUIEventListener(void)
{
}

CIEUIEventListener::~CIEUIEventListener(void)
{
}
HRESULT STDMETHODCALLTYPE CIEUIEventListener::Invoke(
DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS *pDispParams,
VARIANT *pVarResult,
EXCEPINFO *pExcepInfo,
UINT *puArgErr)
{
::MessageBox(NULL,L"FYYYYYYYY",L"Debug",MB_OK);;
return S_OK;
}

最佳答案

如果你的意思是window.postMessage ,您需要从 BHO 的 DOM window 对象 (window.addEventListener("message")) 上添加 message 事件的监听器。要获取 window 对象,请使用 IWebBrowser2::get_DocumentIHTMLDocument2::get_parentWindow,然后查询 window IEventTarget 并调用 addEventListener。为其提供一个 IDispatch 实现作为 listener 参数。当消息发布时,它将被回调为 IDispatch::Invoke(DISPID_VALUE)

[已编辑] 此更新基于您发布的更新代码。我不知道为什么 IEventTarget 仍未为您定义(也许您的 Visual Studio 包含路径配置有问题)。因此,只需从这里获取定义:

MIDL_INTERFACE("305104b9-98b5-11cf-bb82-00aa00bdce0b")
IEventTarget : public IDispatch
{
public:
virtual /* [id] */ HRESULT STDMETHODCALLTYPE addEventListener(
/* [in] */ __RPC__in BSTR type,
/* [in] */ __RPC__in_opt IDispatch *listener,
/* [in] */ VARIANT_BOOL useCapture) = 0;

virtual /* [id] */ HRESULT STDMETHODCALLTYPE removeEventListener(
/* [in] */ __RPC__in BSTR type,
/* [in] */ __RPC__in_opt IDispatch *listener,
/* [in] */ VARIANT_BOOL useCapture) = 0;

virtual /* [id] */ HRESULT STDMETHODCALLTYPE dispatchEvent(
/* [in] */ __RPC__in_opt IDOMEvent *evt,
/* [out][retval] */ __RPC__out VARIANT_BOOL *pfResult) = 0;

};

MIDL_INTERFACE("305104ba-98b5-11cf-bb82-00aa00bdce0b")
IDOMEvent : public IDispatch
{
public:
virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_bubbles(
/* [out][retval] */ __RPC__out VARIANT_BOOL *p) = 0;

virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_cancelable(
/* [out][retval] */ __RPC__out VARIANT_BOOL *p) = 0;

virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_currentTarget(
/* [out][retval] */ __RPC__deref_out_opt IEventTarget **p) = 0;

virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_defaultPrevented(
/* [out][retval] */ __RPC__out VARIANT_BOOL *p) = 0;

virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_eventPhase(
/* [out][retval] */ __RPC__out USHORT *p) = 0;

virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_target(
/* [out][retval] */ __RPC__deref_out_opt IEventTarget **p) = 0;

virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_timeStamp(
/* [out][retval] */ __RPC__out ULONGLONG *p) = 0;

virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_type(
/* [out][retval] */ __RPC__deref_out_opt BSTR *p) = 0;

virtual /* [id] */ HRESULT STDMETHODCALLTYPE initEvent(
/* [in] */ __RPC__in BSTR eventType,
/* [in] */ VARIANT_BOOL canBubble,
/* [in] */ VARIANT_BOOL cancelable) = 0;

virtual /* [id] */ HRESULT STDMETHODCALLTYPE preventDefault( void) = 0;

virtual /* [id] */ HRESULT STDMETHODCALLTYPE stopPropagation( void) = 0;

virtual /* [id] */ HRESULT STDMETHODCALLTYPE stopImmediatePropagation( void) = 0;

virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_isTrusted(
/* [out][retval] */ __RPC__out VARIANT_BOOL *p) = 0;

virtual /* [id][propput] */ HRESULT STDMETHODCALLTYPE put_cancelBubble(
/* [in] */ VARIANT_BOOL v) = 0;

virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_cancelBubble(
/* [out][retval] */ __RPC__out VARIANT_BOOL *p) = 0;

virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_srcElement(
/* [out][retval] */ __RPC__deref_out_opt IHTMLElement **p) = 0;

};

接下来,您的 CIEUIEventListener 看起来不像 COM 对象实现。我没有看到任何 IUnknownIDispatch 方法,也许您只是没有显示它。您也不必从 IDispatchEx 派生,IDispatch 就足够了。我建议您以以下 DOM 事件接收器的实现为基础,它是不言自明的:

// Usage:
//
// CComPtr<CEventSink> eventSink;
// CEventSink::Create(pTestScript, &eventSink); // pass eventSink where IDispatch* is expected
//

class CEventSink:
public CComObjectRoot,
public IDispatch
{
protected:
CTestScript* m_pParent;

CEventSink() { m_pParent = NULL; }

public:
BEGIN_COM_MAP(CEventSink)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()

// create and initialize
static HRESULT Create(CTestScript* pParent, CEventSink** pp)
{
CComObject<CEventSink>* pThis = NULL;
CComObject<CEventSink>::CreateInstance(&pThis);
if (!pThis)
return E_OUTOFMEMORY;

pThis->m_pParent = pParent;

(*pp = pThis)->AddRef();
return S_OK;
}

// IDispatch
STDMETHODIMP GetTypeInfoCount(UINT* pctinfo)
{
return E_NOTIMPL;
}

STDMETHODIMP GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
{
return E_NOTIMPL;
}

STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid)
{
return DISP_E_UNKNOWNNAME;
}

STDMETHODIMP Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
if ( dispidMember == DISPID_VALUE )
{
// handle the event
// for example, call some method on m_pParent
}
return DISP_E_MEMBERNOTFOUND;
}
};

关于events - ATL C++ BHO 中的 Javascript 发布消息事件处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18756704/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com