我用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;
}
我用的开发工具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;
}
解决方案 »
- 6410+wince6的DShow摄像头拍照变色,是驱动问题,还是应用程序写不好
- 如何实现对话框内控件随对话框的拖放改变大小
- GDI+和GDI坐标系统改变导致长度不一致问题
- 请问如何让循环中所有的植都显示在编辑框中?
- 春节要回家,打折机票一票难求啊!!!!!!!
- odbc的问题:数据集OPEN(),出现“连接超时”或语句很长的的连接错误等 对话框,如何让他们消失,变成自己写的对话框?
- ▲▲▲▲▲ 用VC调用crystal的问题,100分求助!! ▲▲▲▲▲
- 关于两个类相互引用的问题!
- CFileDialog 的save file 的问题。
- 《软件项目管理心得》一文
- MFC 关于信号灯的控制
- MFC中光标如何在不同的编辑框中移动?
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);}还是无法实现阿!有哪个高手响应下吗!
vc++ 没试验.
http://support.microsoft.com/kb/249232/zh-cnhttp://blog.csdn.net/suese/archive/2008/03/17/2193088.aspx
我插入脚本的代码是:
在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中,这个我就不懂了 望高手指点,至于删除浏览器的源码我还没有去研究。
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元素修改和添加。
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,这时候怎么些代码来得知网页图片也是完全加载了呢