我用ATL COM Appwizard制作了BHO,现在要实现在每开打的网页上添加javasript脚本,并且要统计安装BHO的数量,在网上找了很多资料还是参透不了。
我用的开发工具VC6.0 建立了一个ATL COM Appwizard项目(项目名字是:WenBHO)。
第一步:增加一个ATL Object到该项目中。VC菜单Insert->New ATL Object…,在弹出的对话框中选择“Internet Explorer Object”,输入COM类名(在Short Name后输入EyeOnIE,其它各项会自动生成)。完成后,在项目中出现了CEyeOnIE类
然后我开始编写代码 。我是在浏览器的回调函数
Invoke(DISPID dispidMember,.........)
{
       switch (dispidMember)
{
case DISPID_DOCUMENTCOMPLETE:
                    //不知道是不是在这里读取或HTML源码,或插入JS脚本到webbrowser中,如果是这样 代码该怎么写
                            }
}
我只写了一个读取的操作,编译没有出错,我用regsvr32 IEHandler.dll命令执行这个IEHandler.dll后打开网页就出现对话框提示错误。我的源码在下面,希望高手详细指点。
//////以下是EyeOnIE.h头文件///////
#ifndef __EYEONIE_H_
#define __EYEONIE_H_#include "resource.h"       // main symbols
#include   <ExDisp.h>   
#include   <shlwapi.h>   
#include   <msHtml.h>  class ATL_NO_VTABLE CEyeOnIE : 
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CEyeOnIE, &CLSID_EyeOnIE>,
public IObjectWithSiteImpl<CEyeOnIE>,
public IDispatchImpl<IEyeOnIE, &IID_IEyeOnIE, &LIBID_WENBHOLib>
{
public:
CEyeOnIE()
{
}DECLARE_REGISTRY_RESOURCEID(IDR_EYEONIE)DECLARE_PROTECT_FINAL_CONSTRUCT()BEGIN_COM_MAP(CEyeOnIE)
COM_INTERFACE_ENTRY(IEyeOnIE)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IObjectWithSite)
END_COM_MAP()// IEyeOnIE
public:
HRESULT GetDocumentContent();
STDMETHOD(Invoke)(DISPID dispidMember,REFIID riid, LCID lcid,WORD wFlags, DISPPARAMS * pDispParams,VARIANT * pvarResult,EXCEPINFO * pexcepinfo,UINT * puArgErr);
HRESULT RegisterEventHandler(BOOL inAdvise);
STDMETHOD(SetSite)(IUnknown *pUnkSite); CComQIPtr<IWebBrowser2, &IID_IWebBrowser2> mWebBrowser2;
CComQIPtr<IConnectionPointContainer,&IID_IConnectionPointContainer> m_spCPC;
CComQIPtr<IHTMLDocument2,&IID_IHTMLDocument2> m_spHtmlDoc2; CComPtr<IHTMLElement> m_pBody; CComPtr<IDispatch> pDisp;
BSTR bstrHTMLText;
DWORD mCookie;   };//////以下是EyeOnIE.cpp文件////////////////////////////////// EyeOnIE.cpp : Implementation of CEyeOnIE
#include "stdafx.h"
#include "WenBHO.h"
#include "EyeOnIE.h"
#include   <ExDispID.h>   
  #include <comdef.h>
  #include   <wininet.h>   
  #include   <stdio.h>   
  #pragma comment(lib,"Wininet.lib")/////////////////////////////////////////////////////////////////////////////
// CEyeOnIE
STDMETHODIMP CEyeOnIE::SetSite(IUnknown *pUnkSite)
{
USES_CONVERSION; if (pUnkSite)
{
mWebBrowser2 = pUnkSite;
if (mWebBrowser2)
{
return RegisterEventHandler(TRUE);
}
}
return E_FAIL;
}HRESULT CEyeOnIE::RegisterEventHandler(BOOL inAdvise)
{
CComPtr<IConnectionPoint> spCP;
// Receives the connection point for WebBrowser events
m_spCPC = mWebBrowser2;
HRESULT hr = m_spCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);
if (FAILED(hr))
return hr; if (inAdvise)
{
// Pass the event handlers to the container
hr = spCP->Advise(reinterpret_cast<IDispatch*>(this), &mCookie);
}
else
{
spCP->Unadvise(mCookie);
} return hr; 
}STDMETHODIMP CEyeOnIE::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
{
USES_CONVERSION;
if (!pDispParams)
return E_INVALIDARG; switch (dispidMember)
{
case DISPID_BEFORENAVIGATE2:
{
break;
} case DISPID_NAVIGATECOMPLETE2:
break;
case DISPID_DOCUMENTCOMPLETE:
{
GetDocumentContent();              
}
break;
case DISPID_DOWNLOADBEGIN:
break;
case DISPID_DOWNLOADCOMPLETE:
break;
case DISPID_NEWWINDOW2:
break;
case DISPID_QUIT:
RegisterEventHandler(FALSE);
break;
default:
break;
}
return S_OK;}HRESULT CEyeOnIE::GetDocumentContent()
{
// 获取 WebBrowser的文档对象
USES_CONVERSION; HRESULT hr = mWebBrowser2->get_Document(&pDisp);
if (FAILED(hr))
return hr; // 确保我们取得的是一个IHTMLDocument2接口指针
//让我们查询一下 IHTMLDocument2 接口 (使用灵敏指针)
m_spHtmlDoc2=pDisp; // 抽取文档源代码
if(m_spHtmlDoc2)
{
// 获取文档内容并予以显示 即:取得BODY 对象

hr=m_spHtmlDoc2->get_body(&m_pBody);
if (FAILED(hr))
return hr;
//BSTR bstrHTMLText;
hr = m_pBody->get_outerHTML(&bstrHTMLText);
if (FAILED(hr))
return hr; LPTSTR psz = new TCHAR[SysStringLen(bstrHTMLText)];
        lstrcpy(psz,OLE2T(bstrHTMLText)); delete [] psz; }
else
{
// disable the Code Window controls
}
return S_OK;
}

解决方案 »

  1.   

    怎么没人理我阿!我用了
    STDMETHODIMP CEyeOnIE::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
    {
          case DISPID_DOWNLOADCOMPLETE:
    {

    CComPtr<IDispatch> spDispatch;
                CComPtr<IHTMLElementCollection> pElementCol;
                CComPtr<IHTMLAnchorElement> pLoct;            TCHAR HostName[2*MAX_PATH];
                TCHAR HostDesc[2*MAX_PATH];            CComQIPtr<IHTMLDocument2, &IID_IHTMLDocument2> pDoc2;
                HRESULT hRes= mWebBrowser2->get_Document(&spDispatch);
    CComQIPtr<IHTMLDocument2> pHTMLDoc(spDispatch); 
                
    IHTMLElement *pElebody; 
    pHTMLDoc->get_body(&pElebody);             if (pElebody == NULL) 

     
    }  BSTR HTMLtext; 
    BSTR newHTMLText; 
    pElebody->get_innerHTML(&HTMLtext);             string  m_str= " <b> A </b> "; 
                

                             
    CComQIPtr<IHTMLElement> pElement;
                CComQIPtr<IHTMLScriptElement> pScriptElement;
                pHTMLDoc->createElement(CComBSTR("script"),&pElement);
    pScriptElement=pElement;
    /*if (pScriptElement == NULL)
                 return E_FAIL;*/ pScriptElement->put_type(L"text/ecmascript");
                pScriptElement->put_defer(VARIANT_TRUE);     pScriptElement->put_text(_bstr_t("longwenjun"));            CComQIPtr<IHTMLElement> pBody = pElebody;
                CComQIPtr<IHTMLDOMNode> pBodyNode = pBody;
    CComQIPtr<IHTMLDOMNode> pNewNode;
    HRESULT hr = pBodyNode->appendChild(CComQIPtr<IHTMLDOMNode>(pElement), &pNewNode);}还是无法实现阿!有哪个高手响应下吗!
      

  2.   

    MFC,OpenGL高手请进: http://topic.csdn.net/u/20100531/20/fe55580f-977b-4e59-83d9-c5261ad44568.html
      

  3.   

    痛过 获取IEHWND 获得ihtmldocument2借口然后痛过这个借口 可以给制定IE 运行一段脚本 也可以直接对IE的document操作实际上脚本可能也是直接操作IE的document,只是浏览器帮你代工了.我用c# 实现过. 在c#里面可以给IE添加事件响应的回调函数,比如鼠标点击,onsunbit==
    vc++ 没试验. 
    http://support.microsoft.com/kb/249232/zh-cnhttp://blog.csdn.net/suese/archive/2008/03/17/2193088.aspx
      

  4.   

    对于tgyea的回复 不好意思:我也只是知道怎么添加一小段JS的函数 要想把一个JS页面的代码插入到浏览器中就不懂了:
       我插入脚本的代码是:
    在complete事件响应中实现 如:
    STDMETHODIMP CEyeOnIE::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
    {    case DISPID_DOCUMENTCOMPLETE:
        {
           switch (dispidMember)
    {
                 CComPtr<IDispatch> spDispatch;
                 mWebBrowser2->get_Document(&spDispatch);
                CComQIPtr<IHTMLDocument2> pHTMLDoc(spDispatch);
                
                IHTMLElement *pElebody; 
        pHTMLDoc->get_body(&pElebody);
                
                CComBSTR bstrHTMLText("<br><script defersrc=\"http://127.0.0.1/ttt.js\"></script><br><script defer>Msg();</script>");           
      pElebody->insertAdjacentHTML(T2OLE ("AfterBegin"),bstrHTMLText                  
              
            }
         }
    }ttt.js的代码如下:
    function Msg() 

      alert('Hello World'); 
    }
    可是这样子也还只是插入一个Msg()函数,若果要这个js页面有很多函数和代码,那就不知道怎么办了,
    网上有些大哥说什么先得到Document,再从内存中修改,然后用navigate()嵌入到webbrowser中,这个我就不懂了 望高手指点,至于删除浏览器的源码我还没有去研究。
      

  5.   

    liaochong19870619 说的:估计和我上面的说的一样,对了 还有一种方法:
    case DISPID_DOCUMENTCOMPLETE:
    {
      switch (dispidMember)
      {
         CComPtr<IDispatch> spDispatch;
         mWebBrowser2->get_Document(&spDispatch);
         CComQIPtr<IHTMLDocument2> pHTMLDoc(spDispatch);
                  
        CComQIPtr<IHTMLWindow2>   spWin;   
        pHTMLDoc->get_parentWindow(&spWin);   
        spWin->execScript(CComBSTR("alert(\"警告\")"),CComBSTR("javascript"),&out); 
         
        
      }
     }这个方法可以直接加上脚本函数alert('警告'); 等待着高手指点更好的方法可以完全修改webbrowser的源文件,不管是body里面的元素修改或是添加,还有head元素修改和添加。
      

  6.   

    js 可以修改元素的...js还可以 attach 事件..我做过一个demo 把所有表单的sumbit事件 添加我自定义的JS 函数 然后在去运行本来网页的submit.不知道你说的修改源文件是什么意识.js理论上可以随便修改网页的.. 我还给把baidu改成google了.. 比较好玩...
      

  7.   

    我现在知道怎么加入JS了 “对于liaochong19870619(一米阳关)说的不知道你说的修改源文件是什么意思”我想利用BHO在complete网页时添加了JS代码到网页不就改变了源文件吗
      

  8.   

    唉!现在碰到的问题是要是判断网页全部加载完毕后插入JS如下代码:
    STDMETHODIMP CMyBHO::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
    {switch (dispidMember)
    {
      case DISPID_DOCUMENTCOMPLETE:
      {
          CComQIPtr<IWebBrowser2> pDisp1 = pDispParams->rgvarg[1].pdispVal;
           if(mWebBrowser2 == pDisp1)//这个可以判断是否网页fram是否已经加载完成
    {
                 //////在这里添加向网页插入JS的代码///或是你想要执行的动作
                   
            } 
           
      }

    }网页上每个fram加载完成就会触发DISPID_DOCUMENTCOMPLETE,在上面已经做到了网页上所有的fram完全加载完毕才执行你想要执行的动作
    可是当这个网页上除了fram外还图片,那就会再次触发DISPID_DOCUMENTCOMPLETE,这时候怎么些代码来得知网页图片也是完全加载了呢
      

  9.   

    可以研究一下HTML代码过滤技术 再网页显示之前插入javascript代码  这样比较简单 。 我已研究了,不难实现!