如何获取IE (控件)的所有链接(包括Frameset, iframe)

IE 顶层 body 节点通过IHTMLElement->get_all 方法无法获取iframe 里面的节点列表:

CComPtr<IHTMLElement> body;
...
CComPtr<IDispatch> spDispCollection;
body->get_all(&spDispCollection);

所以要获取iframe/frame(frameset) 里面的节点列表的话, 则需要根据body/doc 找到frames, 然后从frames -> IHTMLWindow2 -> IHTMLDocument2 . 主要有2个方法, 下面是代码片段:

方法一:

IHTMLDocument2 *pDoc = 浏览器的Document(IWebBrowser2->IDispatch->IHTMLDocument2); 
IHTMLWindow2 *pHTMLWnd = NULL; 
IHTMLDocument2 *pFrameDoc=NULL; 
IHTMLFramesCollection2 *pFramesCollection=NULL; 
LPDISPATCH lpDispatch; 

long p; 
VARIANT varindex,varresult; 
varresult.vt=VT_DISPATCH; 
varindex.vt = VT_I4; 
if(pDoc!=NULL) 
{ 
     HRESULT hr=pDoc->get_frames(&pFramesCollection); 
    if(SUCCEEDED(hr)&&pFramesCollection!=NULL) 
     { 
         hr=pFramesCollection->get_length(&p); 
        if(SUCCEEDED(hr)) 
            for(int i=0; i<p; i++) 
             { 
                 varindex.lVal = i; 
                if(pFramesCollection->item(&varindex, &varresult) ==S_OK) 
                 { 
                     lpDispatch=(LPDISPATCH)varresult.ppdispVal; 
                    if (SUCCEEDED(lpDispatch->QueryInterface(IID_IHTMLWindow2, (LPVOID *)&pHTMLWnd))) 
                     { 
                        if(SUCCEEDED(pHTMLWnd->get_document( &pFrameDoc))) 
                         { 
                            //work with the pFrameDoc获取IE (控件)的所有链接(包括Frameset, iframe) - . - Welcome to the hell 
                         } 
                         pHTMLWnd->Release(); 
                         pHTMLWnd=NULL; 
                     } 
                 } 
             } 
             pFramesCollection->Release(); 
     } 
     pDoc->Release(); 
}

方法二:

CComQIPtr<IHTMLElement> pElem = ; // 可以递归上面的 CComPtr<IDispatch> spDispCollectio 来得到 
CComBSTR bstrTagName;
pElem->get_tagName(&bstrTagName);
if ( lstrcmpiW(L"IFRAME", bstrTagName)==0 ||
         lstrcmpiW(L"FRAME", bstrTagName)==0 )
{
     CComQIPtr<IHTMLFrameBase2>     _framebase2;
     CComPtr<IHTMLWindow2>         _framewindow;
     CComPtr<IHTMLDocument2>         _framedoc;
    
    if( (_framebase2 = spItem) 
        && SUCCEEDED( _framebase2->get_contentWindow(&_framewindow) ) && _framewindow!=NULL 
        && SUCCEEDED( _framewindow->get_document(&_framedoc) ) && _framedoc!=NULL )
     {
        // 对 _framedoc 节点进行处理
     }
}

iframe 跨域访问(cross frame)   zz from : http://codecentrix.blogspot.com/ ... cument-returns.html 
由于安全性限制, 为防止跨域脚本攻击, 当frames 跨域的时候, IHTMLWindow2::get_document 调用将返回 E_ACCESSDENIED 。

下面函数 HtmlWindowToHtmlDocument 对于跨域的frame 通过 IHTMLWindow2 -> IID_IWebBrowserApp -> IHTMLWindow2 绕过了限制。

// Converts a IHTMLWindow2 object to a IHTMLDocument2. Returns NULL in case of failure.
// It takes into account accessing the DOM across frames loaded from different domains.
CComQIPtr<IHTMLDocument2> HtmlWindowToHtmlDocument(CComQIPtr<IHTMLWindow2> spWindow)
{
      ATLASSERT(spWindow != NULL);

      CComQIPtr<IHTMLDocument2> spDocument;
      HRESULT hRes = spWindow->get_document(&spDocument);
    
     if ((S_OK == hRes) && (spDocument != NULL))
      {
          // The html document was properly retrieved.
          return spDocument;
      }

     // hRes could be E_ACCESSDENIED that means a security restriction that
     // prevents scripting across frames that loads documents from different internet domains.
      CComQIPtr<IWebBrowser2>   spBrws = HtmlWindowToHtmlWebBrowser(spWindow);
     if (spBrws == NULL)
      {
          return CComQIPtr<IHTMLDocument2>();
      }

     // Get the document object from the IWebBrowser2 object.
      CComQIPtr<IDispatch> spDisp;
      hRes = spBrws->get_Document(&spDisp);
      spDocument = spDisp;

     return spDocument;
}


// Converts a IHTMLWindow2 object to a IWebBrowser2. Returns NULL in case of failure.
CComQIPtr<IWebBrowser2> HtmlWindowToHtmlWebBrowser(CComQIPtr<IHTMLWindow2> spWindow)
{
      ATLASSERT(spWindow != NULL);

      CComQIPtr<IServiceProvider>   spServiceProvider = spWindow;
     if (spServiceProvider == NULL)
      {
          return CComQIPtr<IWebBrowser2>();
      }

      CComQIPtr<IWebBrowser2> spWebBrws;
      HRESULT hRes = spServiceProvider->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&spWebBrws);
     if (hRes != S_OK)
      {
          return CComQIPtr<IWebBrowser2>();
      }

     return spWebBrws;
}

COM IE控件 链接 IHTMLElement

分享到:
评论加载中,请稍后...
创APP如搭积木 - 创意无限,梦想即时!
回到顶部