本文转载自我2004年在csdn发布的博客
问
在您的网站拜读了关于TWebBrowser
的使用方法,但是一直有一个问题困扰我,就是如何取得frame
嵌套frame
的HTML
的原码,我只是知道单个frame
如何取得源码,但是多个frame
嵌套就没有办法,请教一下!
2004-09-29 23:41:28
答
要得到源代码,必须先得到frame
。访问frame
一般说来有两种方法:
1) 通过WebBrowser
的文档接口得到frame
的集合,再逐一访问。
1
HRESULT IHTMLDocument2::get_frames(IHTMLFramesCollection2 **p);
由IHTMLFramesCollection2
接口的item
方法,可以以frame
的索引号(从0开始)或frame
的名称来访问相应的frame
,pvarResult
则返回一个IDispatch
接口(或一个IDispatch
接口的数组,多层嵌套的情况).
1
HRESULT item(VARIANT *pvarIndex, VARIANT *pvarResult);
例子如下,假设pWin是一个指向主窗口的有效的IHTMLWindow
接口指针。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
......
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
对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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
,是比较正规的方法(能够保持网页的原始格式)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
BOOL CHtmlView::GetSource(CString& refString)
{
BOOL bRetVal = FALSE;
CComPtr<IDispatch> spDisp = GetHtmlDocument();
if (spDisp != NULL)
{
HGLOBAL hMemory;
hMemory = GlobalAlloc(GMEM_MOVEABLE, 0);
if (hMemory != NULL)
{
CComQIPtr<IPersistStreamInit> spPersistStream = spDisp;
if (spPersistStream != NULL)
{
CComPtr<IStream> spStream;
if (SUCCEEDED(CreateStreamOnHGlobal(hMemory, TRUE, &spStream)))
{
spPersistStream->Save(spStream, FALSE);
LPCTSTR pstr = (LPCTSTR) GlobalLock(hMemory);
if (pstr != NULL)
{
// Stream is always ANSI, but CString
// assignment operator will convert implicitly.
bRetVal = TRUE;
TRY
{
refString = pstr;
}
CATCH_ALL(e)
{
bRetVal = FALSE;
DELETE_EXCEPTION(e);
}
END_CATCH_ALL
if(bRetVal == FALSE)
{
GlobalFree(hMemory);
}
else
{
GlobalUnlock(hMemory);
}
}
}
}
}
}
return bRetVal;
}