获取iframe中的内容、查找获取指定元素(关于用c++调用WEBBROWSER控件,使用相关接口操作web页面元素的一些方法)
2017-10-13 10:35
2061 查看
最近开发WINDOWS下的应用程序,需要用到C++中调用WEBBROWSER控件操作网页的相关技术,查阅了一下相关文档,反复调试了几天,对其中的技术有了一些肤浅的认识,大多数C++程序员对COM应该不陌生,其实用C++操作网页,在前端应用层上主要就是对COM接口的查询与使用。以下是我写的一些代码与大家分享一下,总结一下几个关键点,
1、首先要找准元素的接口类型,html的标签(即元素类型,也许我的说法过于肤浅),有关元素类型的定义在mshtml.h头文件基本包括了所有接口类型,要是对web元素接口类型不太了解,可在网上查一下,有很多对定义有中文注释的资料;
2、要对com接口的查询(QueryInterface())格外注意,使用智能指针时的初始化声明,其实也是通过接口查询对指针进行的初始化赋值,接口的查询成败与否,直接关系到能否对网页元素进操作,所以至关重要;
下面是一些代码和简单的注释,希望对需要的朋友们能有所帮助,
//根据类名查找网页元素
CComQIPtr<IHTMLElement> FindWebElement(CComQIPtr<IHTMLElementCollection> pEleColl,string strClassName)
{
CComQIPtr<IHTMLElement> spRetEle;
if(pEleColl == NULL)
{
//所给集合为空时,使用网页控件接口获取顶层页面的全部元素集合(这个是我程序类成员m_pWebBrowserEventHandler->m_pWebClientCall)
CComPtr<IWebBrowser2> pWeb2 = m_pWebBrowserEventHandler->m_pWebClientCall->GetWebBrowser2();
CComPtr<IDispatch> spDp = NULL;
if(pWeb2)
{
HRESULT hr;
hr=pWeb2->get_Document(&spDp);
if(FAILED(hr))
return spRetEle;
}
else
return spRetEle;
CComQIPtr<IHTMLDocument2> pHtmlDoc2 = spDp;
pHtmlDoc2->get_all(&pEleColl);
}
long lCollCount = 0;
pEleColl->get_length(&lCollCount);
long lItem=0;
for(lItem=0; lItem<lCollCount; lItem++)
{
CComPtr<IDispatch> spDp;
HRESULT hr0 = pEleColl->item(CComVariant(lItem),CComVariant(),&spDp);
if( FAILED( hr0 ) ) continue;
CComQIPtr<IHTMLElement, &IID_IHTMLElement> spEleDp(spDp);
if( spEleDp == NULL )continue;
CComBSTR sClassName;
HRESULT hr1 = spEleDp->get_className(&sClassName);
if( FAILED( hr1 ) ) continue;
if(sClassName.Length()==0) continue;
_bstr_t strTemp = sClassName.m_str;
char* pName = strTemp;
if(strClassName.compare(pName) == 0)
{
spRetEle = spEleDp;
break;
}
}
return spRetEle;
}
//遍历搜索子框架,获取所有子框架的HTML文档
vector<string> GetAllSubFrame(CComQIPtr<IHTMLDocument2> spDoc2)
{
string strVal="";
vector<string> sVec;
if(!spDoc2) return sVec;
CComPtr<IHTMLFramesCollection2> spFramesColl;
spDoc2->get_frames(&spFramesColl);
long lCount=0,lItem=0;
CComBSTR sContext;
HRESULT hr = spFramesColl->get_length(&lCount);
if(FAILED(hr)) return sVec;
for(lItem=0; lItem<lCount; lItem++)
{
CComVariant sResultV;
CComVariant sIndex(lItem);
hr = spFramesColl->item(&sIndex,&sResultV);
if(FAILED(hr)) continue;
CComQIPtr<IHTMLWindow2> spWin = sResultV.pdispVal;
if(!spWin) continue;
CComPtr<IHTMLDocument2> spSubDoc;
hr = spWin->get_document(&spSubDoc);
if(FAILED(hr)) continue;
CComQIPtr<IHTMLElement> spBody;
hr = spSubDoc->get_body(&spBody);
if(FAILED(hr)) continue;
spBody->get_outerHTML(&sContext);
_bstr_t bstrStr = sContext.m_str;
char* str = bstrStr;
strVal = str?str:"";
sVec.push_back(strVal);
}
return sVec;
}
//遍历搜索子框架,获取指定ID或NAME的子框架的HTML文档(注意Name有时会有重复,所以ID更为精准些)
string GetSubFrame(CComQIPtr<IHTMLDocument3> spDoc3,string strID,string strName)
{
string strVal;
if(!spDoc3) strVal;
HRESULT hr;
CComBSTR sContext;
CComQIPtr<IHTMLElementCollection> spEleColl;
CComQIPtr<IHTMLElement> spEle, spBody;
CComPtr<IHTMLFrameBase2> spFB2;
CComPtr<IHTMLWindow2> spWin;
CComPtr<IHTMLDocument2> spSubDoc;
CComBSTR sParam = strID.c_str();
if(!strID.empty())
{
//获取指定ID的iframe中<BODY>标签中的内容
//获取元素对象接口
spDoc3->getElementById(sParam,&spEle);
//获取框架根元素对象接口
hr=spEle->QueryInterface(IID_IHTMLFrameBase2,(void**)&spFB2);
if(FAILED(hr)) return strVal;
//获取HTML窗口对象接口
hr=spFB2->get_contentWindow(&spWin);
if(FAILED(hr)) return strVal;
//获取HTML文本对象接口
hr = spWin->get_document(&spSubDoc);
if(FAILED(hr)) return strVal;
//获取BODY元素对象接口
hr = spSubDoc->get_body(&spBody);
if(FAILED(hr)) return strVal;
spBody->get_outerHTML(&sContext);
}
else if(!strName.empty())
{
hr = spDoc3->getElementsByName(sParam,&spEleColl);
if(FAILED(hr)) return strVal;
long lCount=0;
hr = spEleColl->get_length(&lCount);
if(FAILED(hr)) return strVal;
CComPtr<IDispatch> spDp = NULL;
for(long lItem=0; lItem<lCount; ++lItem)
{
//获取name集合中首个匹配的元素
hr = spEleColl->item(CComVariant(strName.c_str()),CComVariant(lItem),&spDp);
if(FAILED(hr)) continue;
break;
}
if(!spDp) return strVal;
//获取元素对象接口
hr = spDp->QueryInterface(IID_IHTMLElement,(void**)&spEle);
if(FAILED(hr)) return strVal;
//获取框架根元素对象接口
hr=spEle->QueryInterface(IID_IHTMLFrameBase2,(void**)&spFB2);
if(FAILED(hr)) return strVal;
//获取HTML窗口对象接口
hr=spFB2->get_contentWindow(&spWin);
if(FAILED(hr)) return strVal;
//获取HTML文本对象接口
hr = spWin->get_document(&spSubDoc);
if(FAILED(hr)) return strVal;
//获取BODY元素对象接口
hr = spSubDoc->get_body(&spBody);
if(FAILED(hr)) return strVal;
spBody->get_outerHTML(&sContext);
}
if(sContext.Length()>0)
{
_bstr_t bstrStr = sContext.m_str;
char* str = bstrStr;
strVal = str?str:"";
}
return strVal;
}
1、首先要找准元素的接口类型,html的标签(即元素类型,也许我的说法过于肤浅),有关元素类型的定义在mshtml.h头文件基本包括了所有接口类型,要是对web元素接口类型不太了解,可在网上查一下,有很多对定义有中文注释的资料;
2、要对com接口的查询(QueryInterface())格外注意,使用智能指针时的初始化声明,其实也是通过接口查询对指针进行的初始化赋值,接口的查询成败与否,直接关系到能否对网页元素进操作,所以至关重要;
下面是一些代码和简单的注释,希望对需要的朋友们能有所帮助,
//根据类名查找网页元素
CComQIPtr<IHTMLElement> FindWebElement(CComQIPtr<IHTMLElementCollection> pEleColl,string strClassName)
{
CComQIPtr<IHTMLElement> spRetEle;
if(pEleColl == NULL)
{
//所给集合为空时,使用网页控件接口获取顶层页面的全部元素集合(这个是我程序类成员m_pWebBrowserEventHandler->m_pWebClientCall)
CComPtr<IWebBrowser2> pWeb2 = m_pWebBrowserEventHandler->m_pWebClientCall->GetWebBrowser2();
CComPtr<IDispatch> spDp = NULL;
if(pWeb2)
{
HRESULT hr;
hr=pWeb2->get_Document(&spDp);
if(FAILED(hr))
return spRetEle;
}
else
return spRetEle;
CComQIPtr<IHTMLDocument2> pHtmlDoc2 = spDp;
pHtmlDoc2->get_all(&pEleColl);
}
long lCollCount = 0;
pEleColl->get_length(&lCollCount);
long lItem=0;
for(lItem=0; lItem<lCollCount; lItem++)
{
CComPtr<IDispatch> spDp;
HRESULT hr0 = pEleColl->item(CComVariant(lItem),CComVariant(),&spDp);
if( FAILED( hr0 ) ) continue;
CComQIPtr<IHTMLElement, &IID_IHTMLElement> spEleDp(spDp);
if( spEleDp == NULL )continue;
CComBSTR sClassName;
HRESULT hr1 = spEleDp->get_className(&sClassName);
if( FAILED( hr1 ) ) continue;
if(sClassName.Length()==0) continue;
_bstr_t strTemp = sClassName.m_str;
char* pName = strTemp;
if(strClassName.compare(pName) == 0)
{
spRetEle = spEleDp;
break;
}
}
return spRetEle;
}
//遍历搜索子框架,获取所有子框架的HTML文档
vector<string> GetAllSubFrame(CComQIPtr<IHTMLDocument2> spDoc2)
{
string strVal="";
vector<string> sVec;
if(!spDoc2) return sVec;
CComPtr<IHTMLFramesCollection2> spFramesColl;
spDoc2->get_frames(&spFramesColl);
long lCount=0,lItem=0;
CComBSTR sContext;
HRESULT hr = spFramesColl->get_length(&lCount);
if(FAILED(hr)) return sVec;
for(lItem=0; lItem<lCount; lItem++)
{
CComVariant sResultV;
CComVariant sIndex(lItem);
hr = spFramesColl->item(&sIndex,&sResultV);
if(FAILED(hr)) continue;
CComQIPtr<IHTMLWindow2> spWin = sResultV.pdispVal;
if(!spWin) continue;
CComPtr<IHTMLDocument2> spSubDoc;
hr = spWin->get_document(&spSubDoc);
if(FAILED(hr)) continue;
CComQIPtr<IHTMLElement> spBody;
hr = spSubDoc->get_body(&spBody);
if(FAILED(hr)) continue;
spBody->get_outerHTML(&sContext);
_bstr_t bstrStr = sContext.m_str;
char* str = bstrStr;
strVal = str?str:"";
sVec.push_back(strVal);
}
return sVec;
}
//遍历搜索子框架,获取指定ID或NAME的子框架的HTML文档(注意Name有时会有重复,所以ID更为精准些)
string GetSubFrame(CComQIPtr<IHTMLDocument3> spDoc3,string strID,string strName)
{
string strVal;
if(!spDoc3) strVal;
HRESULT hr;
CComBSTR sContext;
CComQIPtr<IHTMLElementCollection> spEleColl;
CComQIPtr<IHTMLElement> spEle, spBody;
CComPtr<IHTMLFrameBase2> spFB2;
CComPtr<IHTMLWindow2> spWin;
CComPtr<IHTMLDocument2> spSubDoc;
CComBSTR sParam = strID.c_str();
if(!strID.empty())
{
//获取指定ID的iframe中<BODY>标签中的内容
//获取元素对象接口
spDoc3->getElementById(sParam,&spEle);
//获取框架根元素对象接口
hr=spEle->QueryInterface(IID_IHTMLFrameBase2,(void**)&spFB2);
if(FAILED(hr)) return strVal;
//获取HTML窗口对象接口
hr=spFB2->get_contentWindow(&spWin);
if(FAILED(hr)) return strVal;
//获取HTML文本对象接口
hr = spWin->get_document(&spSubDoc);
if(FAILED(hr)) return strVal;
//获取BODY元素对象接口
hr = spSubDoc->get_body(&spBody);
if(FAILED(hr)) return strVal;
spBody->get_outerHTML(&sContext);
}
else if(!strName.empty())
{
hr = spDoc3->getElementsByName(sParam,&spEleColl);
if(FAILED(hr)) return strVal;
long lCount=0;
hr = spEleColl->get_length(&lCount);
if(FAILED(hr)) return strVal;
CComPtr<IDispatch> spDp = NULL;
for(long lItem=0; lItem<lCount; ++lItem)
{
//获取name集合中首个匹配的元素
hr = spEleColl->item(CComVariant(strName.c_str()),CComVariant(lItem),&spDp);
if(FAILED(hr)) continue;
break;
}
if(!spDp) return strVal;
//获取元素对象接口
hr = spDp->QueryInterface(IID_IHTMLElement,(void**)&spEle);
if(FAILED(hr)) return strVal;
//获取框架根元素对象接口
hr=spEle->QueryInterface(IID_IHTMLFrameBase2,(void**)&spFB2);
if(FAILED(hr)) return strVal;
//获取HTML窗口对象接口
hr=spFB2->get_contentWindow(&spWin);
if(FAILED(hr)) return strVal;
//获取HTML文本对象接口
hr = spWin->get_document(&spSubDoc);
if(FAILED(hr)) return strVal;
//获取BODY元素对象接口
hr = spSubDoc->get_body(&spBody);
if(FAILED(hr)) return strVal;
spBody->get_outerHTML(&sContext);
}
if(sContext.Length()>0)
{
_bstr_t bstrStr = sContext.m_str;
char* str = bstrStr;
strVal = str?str:"";
}
return strVal;
}
相关文章推荐
- Visual Studio 2017中使用正则修改部分内容 如何使用ILAsm与ILDasm修改.Net exe(dll)文件 C#学习-图解教程(1):格式化数字字符串 小程序开发之图片转Base64(C#、.Net) jquery遍历table为每一个单元格取值及赋值 。net加密解密相关方法 .net关于坐标之间一些简单操作
- iframe父页面与子页面之间的元素获取与方法调用
- Jquery调用iframe页面方法、获取节点操作
- ASP.NET母版页中调用内容页的方法和web用户控件调用.aspx页面里的方法
- 【COM范例】WM上获取短信内容,AcitiveX控件调用页面JS方法
- phpcms v9使用GET调用指定id文章内容、页面数据方法
- 六)iframe 及父子页面之间获取元素、方法调用
- phpcms v9使用GET调用指定id文章内容、页面数据方法(get标签什么方法)
- 用Request方法从页面得到Html内容时的处理 及 iframe中控件内容的获取
- js操作cookie;js的setInterval;C#获取指定页面的内容;Ajax.dll的使用
- JavaWeb开发,使用WebBrowser控件调用打印机打印页面
- iframe父、子页面之间页面元素的获取及方法的调用 jquery
- 【COM范例】WM上获取短信内容,AcitiveX控件调用页面JS方法
- [转]Web页面报错: Eval()、XPath() 和 Bind() 这类数据绑定方法只能在数据绑定控件的上下文中使用
- 关于ASP.NET同页面内【用户控件与父页面】以及【用户控件与用户控件】之间方法调用/传值 一点点经验
- 使用Javascript操作DOM的一些方法--元素的访问/复制等
- 使用WebBrowser控件时在网页元素上绘制文本或其他自定义内容
- WinForms C#:html编辑器工程源码,含直接写WebBrowser的文件流、IPersistStreamInit接口的声明和一些相关的小方法
- 关于WEB页面打印的整理(支持页面指定内容的打印)
- 关于子页面调用Masterpage页面变量和控件的方法和实践