我用www.codeproject.com上的一个例子,结合vckbase上扬老师的例子实现了这个要求,但是太慢了足足用了15-20秒。请高人指点

解决方案 »

  1.   

    不要访问IHTMLElementCollection::get_length,用IHTMLElementCollection::get__newEnum
    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
      

  2.   

    自己写过一段,代码复杂,不如这个简单,MARK一下!
      

  3.   

    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)
      

  4.   

    用IHTMLFrameBase::get_marginWidth和IHTMLFrameBase::get_marginHeight
    //mshtml::HTMLFrameBase *fb = dynamic_cast<mshtml::HTMLFrameBase*>(elem);
    fb->marginWidth(...);
    fb->marginHeight(...);
      

  5.   

    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();
    }
    }
      

  6.   

    to lion_wing
    用蒋老大的方法枚举复杂的网页太慢了,用我上面的方法快,但是得不出IHTMLFrameBase接口他永远是NULL
      

  7.   

    to 蒋老大
    是的“Frame元素支持IWebBrowser2接口”但是得不出,正确的“Frame”中的“输入框”位(需要吧Frame偏移加上才行)
      

  8.   

    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();
    }
    }
    }
    }
    不好意思,代码没整理!