FAQ:两种方法访问多层嵌套的frame

** 问========================================
**
在您的网站拜读了关于TWebBrowser的使用方法,但是一直有一个问题困扰我,就是如何取得frame嵌套frame的HTML的原码,我只是知道单个frame如何取得源码,但是多个frame嵌套就没有办法,请教一下!

2004-09-29 23:41:28

答========================================

要得到源代码,必须先得到frame。访问frame一般说来有两种方法:

** 1、通过WebBrowser的文档接口得到frame的集合,再逐一访问。 **

> HRESULT IHTMLDocument2::get_frames(IHTMLFramesCollection2 **p);

由IHTMLFramesCollection2接口的item方法,可以以frame的索引号(从0开始)或frame的名称来访问相应的frame,pvarResult则返回一个IDispatch接口(或一个IDispatch接口的数组,多层嵌套的情况).

> HRESULT item(
> VARIANT *pvarIndex,
> VARIANT *pvarResult
> );

例子如下,假设pWin是一个指向主窗口的有效的IHTMLWindow接口指针。

> ......
> VARIANT frameRequested;
> VARIANT frameOut;
> IHTMLFramesCollection2* pFramesCol;
> IHTMLWindow2* pRightFrameWindow;
> IHTMLDocument2* pRightDoc; > > frameRequested.vt = VT_BSTR; //若为VT_I4则以索引号来访问
> frameRequested.bstrVal = L"rightframe"; //以名称来访问
> //frameRequested.vt = VT_I4;
> //frameRequested.bstrVal = (BSTR)0; > > hr = pWin->get_frames(&pFramesCol);
> hr = pFramesCol->item(&frameRequested, &frameOut);
>
> hr = frameOut.pdispVal->QueryInterface(IID_IHTMLWindow2, (void**)&pRightFrameWindow);
> hr = pRightFrameWindow->get_document(&pRightDoc);
> ......

2、通过IOleContainer枚举嵌入对象的方式来访问WebBrowser对象。

> void CMyHtmlView::RefreshFrames()
> {
> // 取得文档的IDispatch指针
> LPDISPATCH lpDisp = NULL;
> lpDisp = GetHtmlDocument(); > > if (lpDisp)
> {
> IOleContainer* pContainer;
> HRESULT hr = lpDisp->QueryInterface(IID_IOleContainer, (void**)&pContainer);
> lpDisp->Release();
> if (FAILED(hr))
> return hr; > > IEnumUnknown* pEnumerator;
> // 获得枚举器
> hr = pContainer->EnumObjects(OLECONTF_EMBEDDINGS, &pEnumerator);
> pContainer->Release();
> if (FAILED(hr))
> return hr; > > IUnknown* pUnk;
> ULONG uFetched;
> // 枚举并刷新所有frame
> for (UINT i = 0; S_OK == pEnumerator->Next(1, &pUnk, &uFetched); i++)
> {
> IWebBrowser2* pBrowser; > > hr = pUnk->QueryInterface(IID_IWebBrowser2, (void**)&pBrowser);
> pUnk->Release();
> if (SUCCEEDED(hr))
> {
> pBrowser->Refresh();
> pBrowser->Release();
> }
> }
> pEnumerator->Release();
> }

3、访问的多层嵌套frame
注意每个frame又可以包含自己的frame,而上面所说的方法则是针对一个WebBrowser的窗口实现的,并不会涉及到深层的frame。要实现多层嵌套frame的访问,只需要加入一点递归的操作就行了。如对1中的pRightFrameWindow和2中的pBrowser,将函数稍加修改,在得到两个指针后作递归调用即可。

**4、访问源代码
** 下面的方法来自CHtmlView,是比较正规的方法(能够保持网页的原始格式)。

>
> BOOL CHtmlView::GetSource(CString& refString)
> {
> BOOL bRetVal = FALSE;
> CComPtr

 1<idispatch> spDisp = GetHtmlDocument(); 
 2
 3&gt; if (spDisp != NULL)   
 4&gt;  {   
 5&gt;  HGLOBAL hMemory;   
 6&gt;  hMemory = GlobalAlloc(GMEM_MOVEABLE, 0);   
 7&gt;  if (hMemory != NULL)   
 8&gt;  {   
 9&gt;  CComQIPtr<ipersiststreaminit> spPersistStream = spDisp;   
10&gt;  if (spPersistStream != NULL)   
11&gt;  {   
12&gt;  CComPtr<istream> spStream;   
13&gt;  if (SUCCEEDED(CreateStreamOnHGlobal(hMemory, TRUE, &amp;spStream)))   
14&gt;  {   
15&gt;  spPersistStream-&gt;Save(spStream, FALSE); 
16&gt; 
17&gt; LPCTSTR pstr = (LPCTSTR) GlobalLock(hMemory);   
18&gt;  if (pstr != NULL)   
19&gt;  {   
20&gt;  // Stream is always ANSI, but CString   
21&gt;  // assignment operator will convert implicitly. 
22&gt; 
23&gt; bRetVal = TRUE;   
24&gt;  TRY   
25&gt;  {   
26&gt;  refString = pstr;   
27&gt;  }   
28&gt;  CATCH_ALL(e)   
29&gt;  {   
30&gt;  bRetVal = FALSE;   
31&gt;  DELETE_EXCEPTION(e);   
32&gt;  }   
33&gt;  END_CATCH_ALL 
34&gt; 
35&gt; if(bRetVal == FALSE)   
36&gt;  GlobalFree(hMemory);   
37&gt;  else   
38&gt;  GlobalUnlock(hMemory);   
39&gt;  }   
40&gt;  }   
41&gt;  }   
42&gt;  }   
43&gt;  }   
44&gt;    
45&gt;  return bRetVal;   
46&gt;  }   
47&gt;    
48&gt; 
49
50  
51**引用地址:** FAQ:  两种方法访问多层嵌套的frame</istream></ipersiststreaminit></idispatch>
Published At
Categories with Web编程
Tagged with
comments powered by Disqus