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