请问高手怎样才能枚举出网页中所有“输入框”位置(包括IFRAME中),在线等 我用www.codeproject.com上的一个例子,结合vckbase上扬老师的例子实现了这个要求,但是太慢了足足用了15-20秒。请高人指点 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 不要访问IHTMLElementCollection::get_length,用IHTMLElementCollection::get__newEnumvoid ListAllLinkUrls(mshtml::HTMLDocument *myDoc){mshtml::IHTMLElementCollection *elementcollection =dynamic_cast<mshtml::IHTMLElementCollection*>(myDoc->all);if (elementcollection) {System::Collections::IEnumerator *ienum =elementcollection->GetEnumerator();while (ienum && ienum->MoveNext()) {mshtml::IHTMLElement *elem=dynamic_cast<mshtml::IHTMLElement*>(ienum->Current);if (elem) {if (elem->tagName->Equals(S"FRAME")) {mshtml::HTMLFrameBase *fb = dynamic_cast<mshtml::HTMLFrameBase*>(elem);mshtml::HTMLDocument*myDoc2=dynamic_cast<mshtml::HTMLDocument*>(fb->document);ListAllLinkUrls(myDoc2);}else if (elem->tagName->Equals(S"LINK")) {mshtml::HTMLLinkElement *le =dynamic_cast<mshtml::HTMLLinkElement*>(elem);Console::WriteLine("have link {0}",le->href);}}}}} // ListAllLinkUrls 自己写过一段,代码复杂,不如这个简单,MARK一下! to jiangsheng我用你的方法试了一下,分析www.5460.net用了将近6秒,用pIHTMLDocument2->get_frames( &spFramesCollection2 )和pIHTMLDocument2->get_forms( &spElementCollection );遍历用了不到1秒,但是用下面的代码得不出,正确的“IFRAME”中的“输入框”位置(需要吧IFRAME偏移加上才行) pElem->get_offsetHeight(&Height); pElem->get_offsetWidth(&Width); pElem->get_offsetLeft(&Left); pElem->get_offsetTop(&Top); pElem->get_offsetParent(&lpContainer); while ( lpContainer ) { lpContainer->get_offsetLeft(&lValue); Left += lValue; lpContainer->get_offsetTop(&lValue); Top += lValue; lpContainer->get_offsetParent(&lpContainer); }我想问的是怎样由“IHTMLWindow2”得到IFRAME偏移(就是转成IHTMLElement) 用IHTMLFrameBase::get_marginWidth和IHTMLFrameBase::get_marginHeight//mshtml::HTMLFrameBase *fb = dynamic_cast<mshtml::HTMLFrameBase*>(elem);fb->marginWidth(...);fb->marginHeight(...); int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){ ::CoInitialize(NULL); //初始化 COM 公寓 EnumIE(); //枚举浏览器 ::CoUninitialize(); //释放 COM 公寓 cout << _T("======完成======") << endl; getchar(); //等待回车 return 0;}void EnumIE( void ){ cout << _T("开始扫描系统中正在运行的浏览器实例") << endl; CComPtr< IShellWindows > spShellWin; HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows ); if ( FAILED ( hr ) ) { cout << _T("获取 IShellWindows 接口错误") << endl; return; } long nCount = 0; // 取得浏览器实例个数(Explorer 和 IExplorer) spShellWin->get_Count( &nCount ); if( 0 == nCount ) { cout << _T("没有在运行着的浏览器") << endl; return; } for(int i=0; i<nCount; i++) { CComPtr< IDispatch > spDispIE; hr=spShellWin->Item(CComVariant( (long)i ), &spDispIE ); if ( FAILED ( hr ) ) continue; CComQIPtr< IWebBrowser2 > spBrowser = spDispIE; if ( !spBrowser ) continue; CComPtr < IDispatch > spDispDoc; hr = spBrowser->get_Document( &spDispDoc ); if ( FAILED ( hr ) ) continue; CComQIPtr< IHTMLDocument2 > spDocument2 = spDispDoc; if ( !spDocument2 ) continue; // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针 // 删除下行语句的注释,把浏览器的背景改变看看 // spDocument2->put_bgColor( CComVariant( "green" ) ); DWORD dwStart = GetTickCount(); EnumForm( spDocument2 ); //枚举所有的表单 DWORD dwEnd=GetTickCount() ; DWORD x=dwEnd-dwStart; }}void EnumFrame( IHTMLDocument2 * pIHTMLDocument2 ){ if ( !pIHTMLDocument2 ) return; HRESULT hr; CComPtr< IHTMLFramesCollection2 > spFramesCollection2; pIHTMLDocument2->get_frames( &spFramesCollection2 ); //取得框架frame的集合 long nFrameCount=0; //取得子框架个数 hr = spFramesCollection2->get_length( &nFrameCount ); if ( FAILED ( hr ) || 0 == nFrameCount ) return; for(long i=0; i<nFrameCount; i++) { CComVariant vDispWin2; //取得子框架的自动化接口 hr = spFramesCollection2->item( &CComVariant(i), &vDispWin2 ); if ( FAILED ( hr ) ) continue; CComQIPtr< IHTMLWindow2 > spWin2 = vDispWin2.pdispVal; CComQIPtr< IHTMLWindow4 > spWin4 = vDispWin2.pdispVal; if( !spWin2 ) continue; //取得子框架的 IHTMLWindow2 接口 if( !spWin4 ) continue; CComQIPtr< IHTMLFrameBase> fbase; hr=spWin4->get_frameElement(&fbase);//fbase永远是NULL CComPtr < IHTMLDocument2 > spDoc2; spWin2->get_document( &spDoc2 ); //取得字框架的 IHTMLDocument2 接口 EnumForm( spDoc2 ); //递归枚举当前子框架 IHTMLDocument2 上的表单form }}void EnumForm( IHTMLDocument2 * pIHTMLDocument2 ){ if( !pIHTMLDocument2 ) return; EnumFrame( pIHTMLDocument2 ); //递归枚举当前 IHTMLDocument2 上的子框架fram HRESULT hr; CComBSTR bstrTitle; pIHTMLDocument2->get_title( &bstrTitle ); //取得文档标题 USES_CONVERSION; cout << _T("====================") << endl; cout << _T("开始枚举“") << OLE2CT( bstrTitle ) << _T("”的表单") << endl; cout << _T("====================") << endl; CComQIPtr< IHTMLElementCollection > spElementCollection; hr = pIHTMLDocument2->get_forms( &spElementCollection ); //取得表单集合 if ( FAILED( hr ) ) { cout << _T("获取表单的集合 IHTMLElementCollection 错误") << endl; return; } long nFormCount=0; //取得表单数目 hr = spElementCollection->get_length( &nFormCount ); if ( FAILED( hr ) ) { cout << _T("获取表单数目错误") << endl; return; } for(long i=0; i<nFormCount; i++) { IDispatch *pDisp = NULL; //取得第 i 项表单 hr = spElementCollection->item( CComVariant( i ), CComVariant(), &pDisp ); if ( FAILED( hr ) ) continue; CComQIPtr< IHTMLFormElement > spFormElement = pDisp; pDisp->Release(); long nElemCount=0; //取得表单中 域 的数目 hr = spFormElement->get_length( &nElemCount ); if ( FAILED( hr ) ) continue; for(long j=0; j<nElemCount; j++) { CComDispatchDriver spInputElement; //取得第 j 项表单域 hr = spFormElement->item( CComVariant( j ), CComVariant(), &spInputElement ); if ( FAILED( hr ) ) continue; CComVariant vName,vVal,vType; //取得表单域的 名,值,类型 hr = spInputElement.GetPropertyByName( L"name", &vName ); if( FAILED( hr ) ) continue; hr = spInputElement.GetPropertyByName( L"value", &vVal ); if( FAILED( hr ) ) continue; hr = spInputElement.GetPropertyByName( L"type", &vType ); if( FAILED( hr ) ) continue; LPCTSTR lpName = vName.bstrVal? OLE2CT( vName.bstrVal ) : _T("NULL"); //未知域名 LPCTSTR lpVal = vVal.bstrVal? OLE2CT( vVal.bstrVal ) : _T("NULL"); //空值,未输入 LPCTSTR lpType = vType.bstrVal? OLE2CT( vType.bstrVal ) : _T("NULL"); //未知类型 cout << _T("[") << lpType << _T("] "); cout << lpName << _T(" = ") << lpVal << endl; } //想提交这个表单吗?删除下面语句的注释吧 //pForm->submit(); }} to lion_wing用蒋老大的方法枚举复杂的网页太慢了,用我上面的方法快,但是得不出IHTMLFrameBase接口他永远是NULL to 蒋老大是的“Frame元素支持IWebBrowser2接口”但是得不出,正确的“Frame”中的“输入框”位(需要吧Frame偏移加上才行) CComPtr<IHTMLDocument3> pDoc3;hr = pDoc2->QueryInterface(IID_IHTMLDocument3,(void**)&pDoc3) ;if(hr==S_OK){ CComBSTR bstrName("FRAME"); CComPtr<IHTMLElementCollection> pElemCollFrame; hr=pDoc3->getElementsByTagName(bstrName,&pElemCollFrame); if (hr==S_OK) { long pLength; hr=pElemCollFrame->get_length(&pLength); if(hr==S_OK) { for(int i=0;i<pLength;i++) { IDispatch *pDispFrame=NULL; CComVariant vIndex=i; hr=pElemCollFrame->item(vIndex,vIndex,&pDispFrame); if(hr==S_OK) { CComPtr<IHTMLElement> pElemFrame; hr=pDispFrame->QueryInterface(IID_IHTMLElement,(void**)&pElemFrame); if(hr==S_OK) { CComPtr<IHTMLFrameBase2> pFrameBase2; hr=pElemFrame->QueryInterface(IID_IHTMLFrameBase2,(void**)&pFrameBase2); if(hr==S_OK) { CComPtr<IHTMLWindow2> pWindow2; hr=pFrameBase2->get_contentWindow(&pWindow2); if(hr==S_OK) { CComPtr<IHTMLDocument2> pDoc2Frame; hr=pWindow2->get_document(&pDoc2Frame); if (hr==S_OK) { //得到IHTMLDocument2 } } } } } pDispFrame->Release(); } } }}不好意思,代码没整理! 如何删除为ACTIVE添加的事件 CListCtrl 编程 通过IP 获得用户注册信息 如何编程下载网上的图片文件? 请教怎么用vc++画一个3d的球在桌面上实现来回的弹? 通过对话框接收数据库连接字符串的问题!!!急 如何在listbox控件中添加位图,高手帮忙! 如何获取按下一个按钮的时间长短 OPENGL如何局部刷新啊 ?????????? DShow的Filter ax插件里面怎么获取自己的路径? 如果获得不同域IFrame的 IHTMLWindow2 ?? 写一个5K行的管理系统给客户,应该收他多少钱。
void ListAllLinkUrls(mshtml::HTMLDocument *myDoc)
{
mshtml::IHTMLElementCollection *elementcollection =
dynamic_cast<mshtml::IHTMLElementCollection*>(myDoc->all);
if (elementcollection) {
System::Collections::IEnumerator *ienum =
elementcollection->GetEnumerator();
while (ienum && ienum->MoveNext()) {
mshtml::IHTMLElement *elem=dynamic_cast<mshtml::IHTMLElement
*>(ienum->Current);
if (elem) {
if (elem->tagName->Equals(S"FRAME")) {
mshtml::HTMLFrameBase *fb = dynamic_cast<mshtml::HTMLFrameBase*>(elem);
mshtml::HTMLDocument
*myDoc2=dynamic_cast<mshtml::HTMLDocument*>(fb->document);
ListAllLinkUrls(myDoc2);
}
else if (elem->tagName->Equals(S"LINK")) {
mshtml::HTMLLinkElement *le =
dynamic_cast<mshtml::HTMLLinkElement*>(elem);
Console::WriteLine("have link {0}",le->href);
}
}
}
}
} // ListAllLinkUrls
我用你的方法试了一下,分析www.5460.net用了将近6秒,
用pIHTMLDocument2->get_frames( &spFramesCollection2 )和
pIHTMLDocument2->get_forms( &spElementCollection );
遍历用了不到1秒,但是用下面的代码得不出,正确的“IFRAME”中的“输入框”位置(需要吧IFRAME偏移加上才行)
pElem->get_offsetHeight(&Height);
pElem->get_offsetWidth(&Width);
pElem->get_offsetLeft(&Left);
pElem->get_offsetTop(&Top);
pElem->get_offsetParent(&lpContainer); while ( lpContainer )
{
lpContainer->get_offsetLeft(&lValue); Left += lValue;
lpContainer->get_offsetTop(&lValue); Top += lValue;
lpContainer->get_offsetParent(&lpContainer);
}
我想问的是怎样由“IHTMLWindow2”得到IFRAME偏移(就是转成IHTMLElement)
//mshtml::HTMLFrameBase *fb = dynamic_cast<mshtml::HTMLFrameBase*>(elem);
fb->marginWidth(...);
fb->marginHeight(...);
{
::CoInitialize(NULL); //初始化 COM 公寓 EnumIE(); //枚举浏览器 ::CoUninitialize(); //释放 COM 公寓 cout << _T("======完成======") << endl;
getchar(); //等待回车 return 0;
}void EnumIE( void )
{
cout << _T("开始扫描系统中正在运行的浏览器实例") << endl; CComPtr< IShellWindows > spShellWin;
HRESULT hr = spShellWin.CoCreateInstance( CLSID_ShellWindows );
if ( FAILED ( hr ) )
{
cout << _T("获取 IShellWindows 接口错误") << endl;
return;
} long nCount = 0; // 取得浏览器实例个数(Explorer 和 IExplorer)
spShellWin->get_Count( &nCount );
if( 0 == nCount )
{
cout << _T("没有在运行着的浏览器") << endl;
return;
} for(int i=0; i<nCount; i++)
{
CComPtr< IDispatch > spDispIE;
hr=spShellWin->Item(CComVariant( (long)i ), &spDispIE );
if ( FAILED ( hr ) ) continue; CComQIPtr< IWebBrowser2 > spBrowser = spDispIE;
if ( !spBrowser ) continue; CComPtr < IDispatch > spDispDoc;
hr = spBrowser->get_Document( &spDispDoc );
if ( FAILED ( hr ) ) continue; CComQIPtr< IHTMLDocument2 > spDocument2 = spDispDoc;
if ( !spDocument2 ) continue; // 程序运行到此,已经找到了 IHTMLDocument2 的接口指针 // 删除下行语句的注释,把浏览器的背景改变看看
// spDocument2->put_bgColor( CComVariant( "green" ) );
DWORD dwStart = GetTickCount();
EnumForm( spDocument2 ); //枚举所有的表单
DWORD dwEnd=GetTickCount() ;
DWORD x=dwEnd-dwStart;
}
}void EnumFrame( IHTMLDocument2 * pIHTMLDocument2 )
{
if ( !pIHTMLDocument2 ) return; HRESULT hr; CComPtr< IHTMLFramesCollection2 > spFramesCollection2;
pIHTMLDocument2->get_frames( &spFramesCollection2 ); //取得框架frame的集合 long nFrameCount=0; //取得子框架个数
hr = spFramesCollection2->get_length( &nFrameCount );
if ( FAILED ( hr ) || 0 == nFrameCount ) return; for(long i=0; i<nFrameCount; i++)
{
CComVariant vDispWin2; //取得子框架的自动化接口
hr = spFramesCollection2->item( &CComVariant(i), &vDispWin2 );
if ( FAILED ( hr ) ) continue; CComQIPtr< IHTMLWindow2 > spWin2 = vDispWin2.pdispVal;
CComQIPtr< IHTMLWindow4 > spWin4 = vDispWin2.pdispVal;
if( !spWin2 ) continue; //取得子框架的 IHTMLWindow2 接口
if( !spWin4 ) continue;
CComQIPtr< IHTMLFrameBase> fbase;
hr=spWin4->get_frameElement(&fbase);//fbase永远是NULL CComPtr < IHTMLDocument2 > spDoc2;
spWin2->get_document( &spDoc2 ); //取得字框架的 IHTMLDocument2 接口
EnumForm( spDoc2 ); //递归枚举当前子框架 IHTMLDocument2 上的表单form
}
}void EnumForm( IHTMLDocument2 * pIHTMLDocument2 )
{
if( !pIHTMLDocument2 ) return; EnumFrame( pIHTMLDocument2 ); //递归枚举当前 IHTMLDocument2 上的子框架fram HRESULT hr;
CComBSTR bstrTitle;
pIHTMLDocument2->get_title( &bstrTitle ); //取得文档标题 USES_CONVERSION;
cout << _T("====================") << endl;
cout << _T("开始枚举“") << OLE2CT( bstrTitle ) << _T("”的表单") << endl;
cout << _T("====================") << endl; CComQIPtr< IHTMLElementCollection > spElementCollection;
hr = pIHTMLDocument2->get_forms( &spElementCollection ); //取得表单集合
if ( FAILED( hr ) )
{
cout << _T("获取表单的集合 IHTMLElementCollection 错误") << endl;
return;
} long nFormCount=0; //取得表单数目
hr = spElementCollection->get_length( &nFormCount );
if ( FAILED( hr ) )
{
cout << _T("获取表单数目错误") << endl;
return;
}
for(long i=0; i<nFormCount; i++)
{
IDispatch *pDisp = NULL; //取得第 i 项表单
hr = spElementCollection->item( CComVariant( i ), CComVariant(), &pDisp );
if ( FAILED( hr ) ) continue; CComQIPtr< IHTMLFormElement > spFormElement = pDisp;
pDisp->Release(); long nElemCount=0; //取得表单中 域 的数目
hr = spFormElement->get_length( &nElemCount );
if ( FAILED( hr ) ) continue; for(long j=0; j<nElemCount; j++)
{
CComDispatchDriver spInputElement; //取得第 j 项表单域
hr = spFormElement->item( CComVariant( j ), CComVariant(), &spInputElement );
if ( FAILED( hr ) ) continue; CComVariant vName,vVal,vType; //取得表单域的 名,值,类型
hr = spInputElement.GetPropertyByName( L"name", &vName );
if( FAILED( hr ) ) continue;
hr = spInputElement.GetPropertyByName( L"value", &vVal );
if( FAILED( hr ) ) continue;
hr = spInputElement.GetPropertyByName( L"type", &vType );
if( FAILED( hr ) ) continue; LPCTSTR lpName = vName.bstrVal?
OLE2CT( vName.bstrVal ) : _T("NULL"); //未知域名
LPCTSTR lpVal = vVal.bstrVal?
OLE2CT( vVal.bstrVal ) : _T("NULL"); //空值,未输入
LPCTSTR lpType = vType.bstrVal?
OLE2CT( vType.bstrVal ) : _T("NULL"); //未知类型 cout << _T("[") << lpType << _T("] ");
cout << lpName << _T(" = ") << lpVal << endl;
}
//想提交这个表单吗?删除下面语句的注释吧
//pForm->submit();
}
}
用蒋老大的方法枚举复杂的网页太慢了,用我上面的方法快,但是得不出IHTMLFrameBase接口他永远是NULL
是的“Frame元素支持IWebBrowser2接口”但是得不出,正确的“Frame”中的“输入框”位(需要吧Frame偏移加上才行)
hr = pDoc2->QueryInterface(IID_IHTMLDocument3,(void**)&pDoc3) ;
if(hr==S_OK)
{
CComBSTR bstrName("FRAME");
CComPtr<IHTMLElementCollection> pElemCollFrame;
hr=pDoc3->getElementsByTagName(bstrName,&pElemCollFrame);
if (hr==S_OK)
{
long pLength;
hr=pElemCollFrame->get_length(&pLength);
if(hr==S_OK)
{
for(int i=0;i<pLength;i++)
{
IDispatch *pDispFrame=NULL;
CComVariant vIndex=i;
hr=pElemCollFrame->item(vIndex,vIndex,&pDispFrame);
if(hr==S_OK)
{
CComPtr<IHTMLElement> pElemFrame;
hr=pDispFrame->QueryInterface(IID_IHTMLElement,(void**)&pElemFrame);
if(hr==S_OK)
{
CComPtr<IHTMLFrameBase2> pFrameBase2;
hr=pElemFrame->QueryInterface(IID_IHTMLFrameBase2,(void**)&pFrameBase2);
if(hr==S_OK)
{
CComPtr<IHTMLWindow2> pWindow2;
hr=pFrameBase2->get_contentWindow(&pWindow2);
if(hr==S_OK)
{
CComPtr<IHTMLDocument2> pDoc2Frame;
hr=pWindow2->get_document(&pDoc2Frame);
if (hr==S_OK)
{
//得到IHTMLDocument2
}
}
}
}
}
pDispFrame->Release();
}
}
}
}
不好意思,代码没整理!