訪問
========================================
在您的網站拜讀了關於TWebBrowser的使用方法,但是一直有一個問題困擾我,就是如何取得frame嵌套frame的HTML的原碼,我只是知道單個frame如何取得源碼,但是多個frame嵌套就沒有辦法,請教一下!
答========================================
要得到原始碼,必須先得到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<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;
}