vc ++ Web浏览器控件捕获javascript按钮单击事件 [英] vc++ web browser control catching javascript button click events

查看:100
本文介绍了vc ++ Web浏览器控件捕获javascript按钮单击事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以控制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 thisreturn 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆