VC操作Web Browser的若干技巧
来源:互联网 发布:seo霸屏技术 编辑:程序博客网 时间:2024/05/23 19:17
♀ 获取文档的总高度和宽度以及页面当前显示的文档位置
以下代码用于获取页面当前显示的文档位置,如需获取文档的总高度和宽度,只需将函数get_scrollLeft()和get_scrollTop()换为get_scrollWidth()和get_scrollHeight()即可(注意,获取高度和宽度只有当收到WebBrowser的DocumentComplete事件后才有效)。其中m_pUiWeb为指向WebBrowser控件的指针。
因为在WebBrowser中右键菜单是由Docment对象管理的,所以要屏蔽或者修改右键菜单,必须从Docment对象入手,WebBrowser向我们提供了IDocHostUIHandler接口以完成对Docment对象UI的相关操作,在该接口包含有一个ShowContextMenu()函数,通过对该函数的重载我们就可完成屏蔽或者修改右键菜单的任务。那么,我们只剩下了如何将Docment对象原有的UIHandler替换为我们自定义的UIHandler的任务,请参考下面的例子。其中,CDocHostUIHandler为自定义的UIHandler类。
♀ 加载内存中的页面(来自网络,未验证)
或者因为网页保密的考虑;或者因为软件分发的考虑,有的时候就需要让IE或IE浏览器控件显示内存或资源中的HTML网页。在 MFC 中,CHtmlView::LoadFromResource() 可以显示程序资源中的 HTML 内容。我们都知道MFC的CHtmlView其实是对IWebBrowser2的一个包装,但是在 IWebBrowser2 中却没有类似的方法。那么它是如何实现的呢?步骤如下:
1、首先通过IWebBrowser2::Navigate2()显示一个网页,其目的是产生有效的对象,从而得到IHTMLDocument2接口;
2、IWebBrowser2::get_Document() 得到 IHTMLDocument2 接口指针;
3、IHTMLDocument2::QueryInterface() 得到 IPersistStreamInit 接口指针;
4、IPersistStreamInit::InitNew() 初始化接口对象;
5、IPersistStreamInit::Load() 装载内存中的 HTML 数据流(IStream *);
内存指针转换为流的方法是:
I、 GlobalAlloc() 申请内存;
II、 复制 HTML 字符串内容到上述的内存中;
III、CreateStreamFromHGlobal() 转换内存为 IStream 指针;
原理性代码如下:
把 HTML 文件加入到程序资源的方法比较简单,在资源卡片中,鼠标右键弹出菜单,执行 Import...(引入),选择指定的 HTML 文件,然后给一个资源名称即可。(在这里,最方便的资源名称用字符串比较好,如果使用整数ID,那么将来在使用的时候是这样的格式:res://文件名/#101,这里假设 101 是资源的ID号。真麻烦!我不太喜欢这样的方式。)对于图片文件等其它的附件,则需要手工编辑资源 RC 文件(用 IDE 环境引入,它会试图用文本方式打开一个2进制文件,多数情况下会“死机”)。
手工编辑 RC 文件的部分是:
WebBrowser的事件主要包括Control事件、Window事件及Docment事件三大类,微软分别提供了三个虚拟Event结构表示相关事件,分别是:DWebBrowserEvents、HTMLWindowEvents、HTMLDocumentEvents。使用时只需继承、实现相关Event结构,并安装相关事件即可。以下代码演示了如何继承、实现Docment事件。
用VC在网页上绘图主要通过WebBrowser的IElementBehavior接口和IHTMLPainter接口来实现。具体内容参照MSDN中的《Using Rendering Behaviors》说明,该说明中也有相关演示代码。
以下代码用于获取页面当前显示的文档位置,如需获取文档的总高度和宽度,只需将函数get_scrollLeft()和get_scrollTop()换为get_scrollWidth()和get_scrollHeight()即可(注意,获取高度和宽度只有当收到WebBrowser的DocumentComplete事件后才有效)。其中m_pUiWeb为指向WebBrowser控件的指针。
BOOL GetDocPos(LONG &nPosX, LONG &nPosY){ nPosX = 0; nPosY = 0; IHTMLDocument2 *pWebDoc = (IHTMLDocument2*)m_pUiWeb->get_Document(); IHTMLDocument3 *pWebDoc3 = NULL; HRESULT hRes = pWebDoc->QueryInterface(IID_IHTMLDocument3, (void**)&pWebDoc3); if( FAILED(hRes) || NULL == pWebDoc3 ) { return FALSE; } IHTMLElement *pHtmlBody = NULL; hRes = pWebDoc3->get_documentElement(&pHtmlBody); if( FAILED(hRes) || NULL == pHtmlBody ) { return FALSE; } IHTMLElement2 *pHtmlElement = NULL; hRes = pHtmlBody->QueryInterface(IID_IHTMLElement2, (void**)&pHtmlElement); if( FAILED(hRes) || NULL == pHtmlElement ) { return FALSE; } hRes = pHtmlElement->get_scrollLeft(&nPosX); if( FAILED(hRes) ) { nPosX = 0; return FALSE; } hRes = pHtmlElement->get_scrollTop(&nPosY); if( FAILED(hRes) ) { nPosX = 0; nPosY = 0; return FALSE; } return TRUE;}♀ 屏蔽或者修改鼠标右键菜单
因为在WebBrowser中右键菜单是由Docment对象管理的,所以要屏蔽或者修改右键菜单,必须从Docment对象入手,WebBrowser向我们提供了IDocHostUIHandler接口以完成对Docment对象UI的相关操作,在该接口包含有一个ShowContextMenu()函数,通过对该函数的重载我们就可完成屏蔽或者修改右键菜单的任务。那么,我们只剩下了如何将Docment对象原有的UIHandler替换为我们自定义的UIHandler的任务,请参考下面的例子。其中,CDocHostUIHandler为自定义的UIHandler类。
void NavigateComplete2(LPDISPATCH pDisp, VARIANT* URL){ // 判断事件通知对象 LPUNKNOWN pUnknown = m_pUiWeb->GetControlUnknown(); if( NULL == pUnknown ) { return; } LPUNKNOWN pUnknownWeb = NULL; LPUNKNOWN pUnknownDisp = NULL; HRESULT hr = pUnknown->QueryInterface(IID_IUnknown, (LPVOID*)&pUnknownWeb); if( FAILED(hr) ) { return; } hr = pDisp->QueryInterface(IID_IUnknown, (LPVOID*)&pUnknownDisp); if( FAILED(hr) || pUnknownWeb != pUnknownDisp) { pUnknownWeb->Release(); return; } pUnknownWeb->Release(); pUnknownDisp->Release(); // 修改Document对象 if( NULL == m_pDocHostUiHandler ) { m_pDocHostUiHandler = new CDocHostUIHandler(); } IHTMLDocument2 *pHtmlDoc2 = (IHTMLDocument2*)m_pUiWeb->get_Document(); ICustomDoc *pCustomDoc = NULL; hr = pHtmlDoc2->QueryInterface(IID_ICustomDoc, reinterpret_cast(&pCustomDoc)); if( FAILED(hr) ) { return; } pCustomDoc->SetUIHandler(m_pDocHostUiHandler); pCustomDoc->Release();}以下代码演示了如何屏蔽右键菜单:
STDMETHODIMP CDocHostUIHandler::QueryInterface(REFIID riid, PVOID* pInterface){ *pInterface = NULL; if (riid==IID_IUnknown) { *pInterface=this; } else if (riid==IID_IDocHostUIHandler) { *pInterface=this; } if(*pInterface) { AddRef(); return S_OK; } return E_NOINTERFACE;} STDMETHODIMP CDocHostUIHandler::ShowContextMenu(DWORD dwID, POINT* pPt, IUnknown* pcmdtReserved, IDispatch* pdispreserved){ return S_OK;}注意,由于微软提供的IDocHostUIHandler接口是继承自IUnknown的虚拟结构,所以如果要实现该接口,则必须实现该结构下的所有函数,对于不必做修改,只需保持原有功能的函数直接返回“E_NOTIMPL”即可。
♀ 加载内存中的页面(来自网络,未验证)
或者因为网页保密的考虑;或者因为软件分发的考虑,有的时候就需要让IE或IE浏览器控件显示内存或资源中的HTML网页。在 MFC 中,CHtmlView::LoadFromResource() 可以显示程序资源中的 HTML 内容。我们都知道MFC的CHtmlView其实是对IWebBrowser2的一个包装,但是在 IWebBrowser2 中却没有类似的方法。那么它是如何实现的呢?步骤如下:
1、首先通过IWebBrowser2::Navigate2()显示一个网页,其目的是产生有效的对象,从而得到IHTMLDocument2接口;
2、IWebBrowser2::get_Document() 得到 IHTMLDocument2 接口指针;
3、IHTMLDocument2::QueryInterface() 得到 IPersistStreamInit 接口指针;
4、IPersistStreamInit::InitNew() 初始化接口对象;
5、IPersistStreamInit::Load() 装载内存中的 HTML 数据流(IStream *);
内存指针转换为流的方法是:
I、 GlobalAlloc() 申请内存;
II、 复制 HTML 字符串内容到上述的内存中;
III、CreateStreamFromHGlobal() 转换内存为 IStream 指针;
原理性代码如下:
// 显示一个空白网页m_ie.Navigate2( &CComVariant(_T("about:blank")),NULL,NULL,NULL,NULL); // 得到 IHTMLDocument2 指针CComPtr< IDispatch > spDoc(m_ie.GetDocument()); // 得到 IPersistStreamInit 指针CComQIPtr< IPersistStreamInit, &IID_IPersistStreamInit > spPSI( spDoc ); // 申请内存,复制 HTML 字符串LPTSTR lpMem = (LPTSTR)::GlobalAlloc( GPTR, ::lstrlen( lpHtml )+1 );lstrcpy( lpMem, "xxx xxx" ); // 转换内存为流对象指针CComPtr< IStream > spStream;CreateStreamOnHGlobal( lpMem, TRUE, &spStream ); // 初始化后,装载显示spPSI->InitNew();spPSI->Load( spStream );IE 所能支持的数据传输协议,除了大家所熟悉的 http、ftp、file......还有一个协议是 res ,它表示浏览显示文件中的 HTML 资源。你可以在 IE 的地址栏上直接输入这样格式的 URL:"res://文件名/资源名"。
把 HTML 文件加入到程序资源的方法比较简单,在资源卡片中,鼠标右键弹出菜单,执行 Import...(引入),选择指定的 HTML 文件,然后给一个资源名称即可。(在这里,最方便的资源名称用字符串比较好,如果使用整数ID,那么将来在使用的时候是这样的格式:res://文件名/#101,这里假设 101 是资源的ID号。真麻烦!我不太喜欢这样的方式。)对于图片文件等其它的附件,则需要手工编辑资源 RC 文件(用 IDE 环境引入,它会试图用文本方式打开一个2进制文件,多数情况下会“死机”)。
手工编辑 RC 文件的部分是:
......///////////////////////////////////////////////////////////////////////////////// HTML//// 这两个是HTML文件,可以引入HTML_TOWORD HTML DISCARDABLE "res\\ToWord.htm"HTML_DLG HTML DISCARDABLE "res\\html_dlg.htm"// 下面的是GIF文件,需要手工加入~SEND_R1_C1.GIF HTML DISCARDABLE "res\\~Send_r1_c1.gif"~SEND_R1_C2.GIF HTML DISCARDABLE "res\\~Send_r1_c2.gif"LOGO.GIF HTML DISCARDABLE "res\\Logo.gif"SEND_R1_C1.GIF HTML DISCARDABLE "res\\Send_r1_c1.gif"SEND_R1_C2.GIF HTML DISCARDABLE "res\\Send_r1_c2.gif"SPACER.GIF HTML DISCARDABLE "res\\spacer.gif"#endif // Chinese (P.R.C.) resources/////////////////////////////////////////////////////////////////////////////♀ 响应事件
WebBrowser的事件主要包括Control事件、Window事件及Docment事件三大类,微软分别提供了三个虚拟Event结构表示相关事件,分别是:DWebBrowserEvents、HTMLWindowEvents、HTMLDocumentEvents。使用时只需继承、实现相关Event结构,并安装相关事件即可。以下代码演示了如何继承、实现Docment事件。
// 事件类定义classCHtmlDocEvents : public HTMLDocumentEvents{public: CHtmlDocEvents(); ~CHtmlDocEvents(); DWORD m_dwCount;protected: virtual STDMETHODIMP QueryInterface(REFIID,void**); virtual STDMETHODIMP_(DWORD) AddRef(); virtual STDMETHODIMP_(DWORD) Release(); virtual STDMETHODIMP GetTypeInfoCount(UINT*); virtual STDMETHODIMP GetTypeInfo(UINT,LCID,ITypeInfo**); virtual STDMETHODIMP GetIDsOfNames(REFIID,LPOLESTR*,UINT,LCID,DISPID*); virtual STDMETHODIMP Invoke(DISPID,REFIID,LCID,WORD,DISPPARAMS*, VARIANT*,EXCEPINFO*,UINT*);}; // 事件类实现STDMETHODIMP CHtmlDocEvents::QueryInterface(REFIID riid, PVOID* ppInterface){ *ppInterface = 0; if (riid==IID_IUnknown) { *ppInterface = this; } else if (riid==IID_IDispatch) { *ppInterface = this; } else if (riid==DIID_HTMLDocumentEvents) { *ppInterface = this; } if (*ppInterface) { (*reinterpret_cast(ppInterface))->AddRef(); return S_OK; } return E_NOINTERFACE;} STDMETHODIMP_(DWORD) CHtmlDocEvents::AddRef(){ m_dwCount++; return m_dwCount;} STDMETHODIMP_(DWORD) CHtmlDocEvents::Release(){ m_dwCount--; return m_dwCount;} STDMETHODIMP CHtmlDocEvents::GetIDsOfNames(REFIID, LPOLESTR*, UINT, LCID, DISPID*){ return E_NOTIMPL;} // ……// …… STDMETHODIMP CHtmlDocEvents::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr){ switch (dispidMember) { case DISPID_HTMLDOCUMENTEVENTS_ONMOUSEMOVE: case DISPID_HTMLDOCUMENTEVENTS_ONHELP: case DISPID_HTMLDOCUMENTEVENTS_ONCLICK: case DISPID_HTMLDOCUMENTEVENTS_ONDBLCLICK: case DISPID_HTMLDOCUMENTEVENTS_ONKEYDOWN: case DISPID_HTMLDOCUMENTEVENTS_ONKEYUP: case DISPID_HTMLDOCUMENTEVENTS_ONKEYPRESS: case DISPID_HTMLDOCUMENTEVENTS_ONMOUSEDOWN: case DISPID_HTMLDOCUMENTEVENTS_ONMOUSEUP: case DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOUT: case DISPID_HTMLDOCUMENTEVENTS_ONMOUSEOVER: case DISPID_HTMLDOCUMENTEVENTS_ONREADYSTATECHANGE: case DISPID_HTMLDOCUMENTEVENTS_ONBEFOREUPDATE: case DISPID_HTMLDOCUMENTEVENTS_ONAFTERUPDATE: case DISPID_HTMLDOCUMENTEVENTS_ONROWEXIT: case DISPID_HTMLDOCUMENTEVENTS_ONROWENTER: case DISPID_HTMLDOCUMENTEVENTS_ONDRAGSTART: case DISPID_HTMLDOCUMENTEVENTS_ONSELECTSTART: case DISPID_HTMLDOCUMENTEVENTS_ONERRORUPDATE: default: return E_NOTIMPL; } return NOERROR;} // ……以下代码演示了如何安装Window和Docment事件,其中m_pUiWeb为指向WebBrowser对象的指针,m_pHtmlWindowEvents为指向自定义Window事件对象的指针,m_pHtmlDocEvents为指向CHtmlDocEvents对象的指针:
void DocumentCompleteUiWeb(LPDISPATCH pDisp, VARIANT* URL){ LPUNKNOWN pUnknown = m_pUiWeb->GetControlUnknown(); if( NULL == pUnknown ) { return; } LPUNKNOWN pUnknownWeb = NULL; LPUNKNOWN pUnknownDisp = NULL; HRESULT hr = pUnknown->QueryInterface(IID_IUnknown, (LPVOID*)&pUnknownWeb); if( FAILED(hr) ) { return; } hr = pDisp->QueryInterface(IID_IUnknown, (LPVOID*)&pUnknownDisp); if( FAILED(hr) || pUnknownWeb != pUnknownDisp) { pUnknownWeb->Release(); return; } pUnknownWeb->Release(); pUnknownDisp->Release(); IHTMLDocument2 *pHtmlDoc2 = (IHTMLDocument2*)m_pUiWeb->get_Document(); IConnectionPointContainer* pCPC = NULL; DWORD dwCookie = 0; {// 安装Web Window事件 IHTMLWindow2 *pHtmlWnd2 = NULL; hr = pHtmlDoc2->get_parentWindow(&pHtmlWnd2); if( FAILED(hr) ) { return; } hr = pHtmlWnd2->QueryInterface(IID_IConnectionPointContainer, reinterpret_cast(&pCPC)); if(FAILED(hr)) { return; } IConnectionPoint* pCP = NULL; pCPC->FindConnectionPoint(DIID_HTMLWindowEvents2, &pCP); // 找到安装点 if( NULL == m_pHtmlWindowEvents ) { m_pHtmlWindowEvents = new CHtmlWindowEvents(this); } hr = pCP->Advise(m_pHtmlWindowEvents, &dwCookie); //安装 if( SUCCEEDED(hr) ) { pCP->Release(); } pCPC->Release(); } {// 安装Web Document事件 hr = pHtmlDoc2->QueryInterface(IID_IConnectionPointContainer, reinterpret_cast(&pCPC)); if(FAILED(hr)) { return; } IConnectionPoint* pCP = NULL; pCPC->FindConnectionPoint(DIID_HTMLDocumentEvents2, &pCP); // 找到安装点 if( NULL == m_pHtmlDocEvents ) { m_pHtmlDocEvents = new CHtmlDocEvents(this, m_pMaskWnd, m_pUiWeb, m_pPosIconWnd); } hr = pCP->Advise(m_pHtmlDocEvents, &dwCookie); // 安装 if( SUCCEEDED(hr) ) { pCP->Release(); } pCPC->Release(); }}♀ 用VC在网页中绘图
用VC在网页上绘图主要通过WebBrowser的IElementBehavior接口和IHTMLPainter接口来实现。具体内容参照MSDN中的《Using Rendering Behaviors》说明,该说明中也有相关演示代码。
0 1
- VC操作Web Browser的若干技巧
- VC操作Web Browser的若干技巧
- VC的若干实用小技巧 (转)
- VC的若干实用小技巧
- VC的若干实用小技巧
- VC的若干实用小技巧 (转)
- vc++的若干实用小技巧
- VC的若干实用小技巧(一)
- VC的若干实用小技巧(二)
- VC的若干实用小技巧(三)
- VC的若干实用小技巧(四)
- [转]VC的若干实用小技巧
- VC的若干实用小技巧
- VC的若干实用小技巧
- vc++的若干实用小技巧
- VC的若干实用小技巧[转]
- VC的若干实用小技巧收藏
- VC的若干实用小技巧(三)
- java 日历查询小笔记
- 程序员前途的杀手
- django用户认证
- SSL支持的认证密钥交换方法
- 《Head First 设计模式》学习笔记——单件模式
- VC操作Web Browser的若干技巧
- Java执行批处理.bat文件(有问题???求高手帮忙解答!!!)
- 因权限引起的svn提交失败的错误及其解决办法
- Socket----HTTP
- OpenCV编程->OpenCV2.4.8配置
- Findbugs、PMD、CheckStyle使用分析报告
- R language
- 托管线程处理的最佳做法
- hadoop备战:yarn框架的简介(mapreduce2)