vc ++ Web浏览器控件捕获javascript按钮单击事件 [英] vc++ web browser control catching javascript button click events
问题描述
我可以控制Web浏览器,并且可以使用IHTMLDocument界面.我正在尝试捕获Web浏览器控件中页面内发生的事件,但不确定如何获取这些事件的句柄.
我想做的是:
1)导航到使用javascript浏览其网站的网站.
2)捕获按钮按下以及与之相关的javascript函数
2)将它们发布到我的网页的另一个实例.
我有第1部分和第3部分.
任何人都可以帮助快速捕获JavaScript事件吗?
在此先感谢
I have web browser control and I have acess to the IHTMLDocument interface. I am trying to catch events that occur within a page in my web browser control but am not sure how to get a handle to these events.
What I want to do is:
1) navigate to a website that uses javascript to navigate through its website.
2) capture button presses and the javascript function associated with them
2) post them to another instance of my web page.
I have parts 1 and 3.
Can anyone help with capturing javascript events on the fly?
Thanks in advance
推荐答案
快速调查一下,文档会建议您使用 ^ ]
然后,脚本引擎 [ ^ ]您
a quick scoot round the docs would suggest you can get to the scripting engine via the document, using IHTMLDocument::Script[^]
Then there should be something inside the Script Engine[^] that could help you
您需要使用代码中的连接点接收Web Browswer事件. 此 [
You need to sink the Web Browswer events using connection points in your code. This [^] may give some pointer to you.
将它们全部获取很长的路要走:
+首先,您需要一个处理程序(作为IDispatch更好的IDispatchEx)
Its a long way to get them all:
+ first you need a handler (as IDispatch better IDispatchEx)
#include <dispex.h>
class iDummy : public IDispatchEx
{
public: // IUnknown
virtual HRESULT __stdcall QueryInterface(REFIID riid,void **ppv)
{
if(IID_IUnknown ==riid) return *(IUnknown **)ppv=this,AddRef();S_OK;
if(IID_IDispatch ==riid) return *(IDispatch **)ppv=this,AddRef();S_OK;
if(IID_IDispatchEx==riid) return *(IDispatchEx**)ppv=this,AddRef();S_OK;
return E_NOINTERFACE;
}
virtual ULONG __stdcall AddRef(){ return InterlockedIncrement(&_ref); }
virtual ULONG __stdcall Release(){ if(InterlockedDecrement(&_ref)) return _ref; delete this; return 0; }
public: // IDispatch
virtual HRESULT __stdcall GetTypeInfoCount(UINT *pctinfo)
{ return E_NOTIMPL; }
virtual HRESULT __stdcall GetTypeInfo(UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo)
{ return E_NOTIMPL; }
virtual HRESULT __stdcall GetIDsOfNames(REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId)
{ unsigned int i; for(i=0;(i<cNames) && (S_OK==GetDispID(rgszNames[i],0,rgDispId+i));i++); return i<cNames?DISP_E_MEMBERNOTFOUND:S_OK; }
virtual HRESULT __stdcall Invoke(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr)
{ return InvokeEx(dispIdMember,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,0); }
public: // IDispatchEx
virtual HRESULT __stdcall GetDispID(BSTR bstrName,DWORD grfdex,DISPID *pid)
{ TRACE(__TEXT("call: %s\r\n"),bstrName); return E_NOTIMPL; }
virtual HRESULT __stdcall InvokeEx(DISPID id,LCID lcid,WORD wFlags,DISPPARAMS *pdp,VARIANT *pvarRes,EXCEPINFO *pei,IServiceProvider *pspCaller)
{ if(0==id){ Beep(3000,100); }return E_NOTIMPL; }
virtual HRESULT __stdcall DeleteMemberByName(BSTR bstrName,DWORD grfdex)
{ return E_NOTIMPL; }
virtual HRESULT __stdcall DeleteMemberByDispID(DISPID id)
{ return E_NOTIMPL; }
virtual HRESULT __stdcall GetMemberProperties(DISPID id,DWORD grfdexFetch,DWORD *pgrfdex)
{ return E_NOTIMPL; }
virtual HRESULT __stdcall GetMemberName(DISPID id,BSTR *pbstrName)
{ return E_NOTIMPL; }
virtual HRESULT __stdcall GetNextDispID(DWORD grfdex,DISPID id,DISPID *pid)
{ return E_NOTIMPL; }
virtual HRESULT __stdcall GetNameSpaceParent(IUnknown **ppunk)
{ return E_NOTIMPL; }
public:
iDummy(){ _ref=1; }
private:
long _ref;
};
+接下来,即使加载已准备就绪,您也必须遍历所有HTML元素(检查Web浏览器控件的就绪状态):
+ next you have to walk all the HTML elements, even if the load is ready (examine the ready state of the web browser control):
enum { childNodes, length, };
typedef void (*FNWALK)(IDispatch* node);
void WalkNode(IDispatch* node,BSTR* anames,FNWALK fn)
{
VARIANT ret1 = { VT_EMPTY, };
VARIANT ret2 = { VT_EMPTY, };
VARIANT ret3 = { VT_EMPTY, };
VARIANT ret4 = { VT_EMPTY, };
fn(node);
if(S_OK==InvokeName(node,anames[childNodes],ret1))
{
if(VT_DISPATCH==ret1.vt)
{
if(S_OK==InvokeName(ret1.pdispVal,anames[length],ret2))
{
if(VT_I4==ret2.vt)
{
wchar_t num[32];
ret3.vt = VT_I4;
for(ret3.lVal=0;ret3.lVal<ret2.lVal;ret3.lVal++)
{
_itow_s(ret3.lVal,num,sizeof(num)/sizeof(num[0]),16);
if(S_OK==InvokeName(ret1.pdispVal,num,ret4))
{
if(VT_DISPATCH==ret4.vt)
{
WalkNode(ret4.pdispVal,anames,fn);
}
VariantClear(&ret4);
}
}
}
VariantClear(&ret2);
}
}
VariantClear(&ret1);
}
}
void WalkDocument(IDispatch* doc,FNWALK fn)
{
BSTR anames[8];
anames[childNodes] = ::SysAllocString(L"childNodes");
anames[length] = ::SysAllocString(L"length");
WalkNode(doc,anames,fn);
for(int i=0;i<=length;i++) SysFreeString(anames[i]);
}
+需要一些辅助功能,如下所示:
+ some helper functions needed as follows:
HRESULT InvokeName(IDispatch* node,BSTR name,VARIANT& ret)
{
HRESULT hr = E_FAIL;
if(node)
{
DISPID did = 0;
DISPPARAMS arg = { 0,0,0,0 };
if(S_OK==node->GetIDsOfNames(IID_NULL,&name,1,0,&did))
{
hr = node->Invoke(did,IID_NULL,0,DISPATCH_PROPERTYGET,&arg,&ret,0,0);
}
}
return hr;
}
HRESULT InvokeWithParams(IDispatch* node,BSTR name,VARIANT* aparam,const unsigned int nparam,VARIANT& ret)
{
HRESULT hr = E_FAIL;
if(node)
{
DISPID did = 0;
DISPPARAMS arg = { aparam,0,nparam,0 };
if(S_OK==node->GetIDsOfNames(IID_NULL,&name,1,0,&did))
{
hr = node->Invoke(did,IID_NULL,0,(0<nparam?DISPATCH_PROPERTYPUT:DISPATCH_PROPERTYGET),&arg,&ret,0,0);
}
}
return hr;
}
+实现walk函数以替换您要替换的事件处理程序:
+ implement the walk function to replace the event handlers you want to replace:
void __fnWalk(IDispatch* node)
{
BSTR nodeName = L"nodeName";
VARIANT ret1 = { VT_EMPTY, };
VARIANT ret2 = { VT_EMPTY, };
VARIANT ret3 = { VT_EMPTY, };
if(S_OK==InvokeName(node,nodeName,ret1))
{
if(VT_BSTR==ret1.vt)
{
TRACE(__TEXT("name: %s\r\n"),ret1.bstrVal);
// if(!_wcsicmp(L"INPUT",ret1.bstrVal) || !_wcsicmp(L"BUTTON",ret1.bstrVal))
{
if(S_OK==InvokeName(node,L"OnClick",ret2))
{
if(VT_DISPATCH==ret2.vt)
{
VARIANT a[8];
unsigned int n = 0;
a[n].pdispVal = new iDummy;
a[n].vt = VT_DISPATCH;
++n;
if(S_OK==InvokeWithParams(node,L"OnClick",a,n,ret3))
{
VariantClear(&ret3);
}
while(0<n) VariantClear(a+(--n));
}
VariantClear(&ret2);
}
}
}
VariantClear(&ret1);
}
++__walkdone;
}
+最后是可以使用所有代码的代码:
+ finally the code you can use all of this:
IDispatch* doc = m_web.get_Document();
if(doc)
{
__walkdone = 0;
WalkDocument(doc,__fnWalk);
doc->Release();
}
对功能进行了测试,并以简单的形式工作.
祝你好运.
Functions are tested and work with a simple form.
Good luck.
这篇关于vc ++ Web浏览器控件捕获javascript按钮单击事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!