zoukankan      html  css  js  c++  java
  • 获取IE (控件)的所有链接(包括Frameset, iframe)

    获取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 
                            } 
                            pHTMLWnd->Release(); 
                            pHTMLWnd=NULL; 
                        } 
                    } 
                } 
                pFramesCollection->Release(); 
        } 
        pDoc->Release(); 
    }

    方法二:
    CComQIPtr<IHTMLElement> pElem = ; // 可以递归上面的 CComPtr<IDispatch> spDispCollection 来得到 
    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/2007/10/when-ihtmlwindow2getdocument-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;
    }


    附: 
    IE(控件/接口)中主要有4个部分, Browser, Document, Frame/IFrame, Element , 其对应接口分别是 
    Browser         -    IWebBrowser2
    Document      -    IHTMLDocument2
    Frame/IFrame-    IHTMLWindow2
    Element         -    IHTMLElement
    可以通过下面方法互相获取 
    browser      -> document        IWebBrowser2::get_Document
    document     -> frame           IHTMLDocument2::get_parentWindow
    frame        -> document        IHTMLWindow2::get_document
    frame        -> parent frame    IHTMLWindow2::get_parent
    frame        -> children frames IHTMLWindow2::get_frames
    element     -> Frame             IHTMLElement->QI(IHTMLFrameBase2) -> IHTMLFrameBase2->get_contentWindow -> IHTMLWindow2 

    ref: 
    在多Frame的网页中怎么取出各个Frame的IHTMLDocument2的接口!急用.(高分)
    在文章 When IHTMLWindow2::get_document returns E_ACCESSDENIED 解决了iframe 跨域访问的问题 

    posted on 2008-07-30 19:17 泡泡牛 阅读(5153) 评论(3)  编辑 收藏 引用 所属分类: Develop

     

  • 相关阅读:
    js 为表格增加行 动态
    百度测试新搜索结果页面 改进灵感来自谷歌?
    多线程程序中使用fork的问题
    C++ struct和class的区别
    J2SE 5 HotSpot JVM 解释
    并行优化、xvout
    C++基础:纯虚函数和抽象类
    C++的四种cast
    logcat过滤输出
    C++虚函数和纯虚函数(2)
  • 原文地址:https://www.cnblogs.com/honeynm/p/4438305.html
Copyright © 2011-2022 走看看