웹브라우저 컨트롤을 사용할 때, 프로그램에서 로드된 도큐먼트의 소스를 가져오고 싶을 때가 있다. 인터넷 익스플로러에서 `보기` / `소스` 를 했을 때처럼 말이다. 쉬울듯하나 그리 간단하지는 않다.
제일 쉬운방법은 IHTMLDocument3에 있는 documentElement 개체를 얻어다 이것의 OuterHTML 프로퍼티를 읽어오는 것이다. 제법 그럴듯한 게 나오므로 대부분의 경우 이 방법을 사용하면 문제가 없다. 단 하나의 문제는 여기에 나오는 것이 웹서버가 준 도큐먼트 소스가 아니라 인터넷 익스플로러의 HTML 파서가 한 번 파싱해 놓은 도큐먼트라는 것이다. 그래서 서버가 준 것과 똑 같은 도큐먼트를 얻고자 할 때는 사용할 수가 없다.
그래서 일반적으로 할 수 있는 방법은 IHTMLDocument2로부터 IPersistStreamInit을 얻어와서 이것의 Save() 메쏘드를 이용하는 것이다. 이걸 할려면 IStream 개체가 있어야 하는데 ::CreateStreamOnHGlobal()이라는 아주 훌륭한 넘으로 쉽게 맹글 수 있다. 처음엔 HGlobal을 만들고 위에 함수를 불렀는데, 읽어올 도큐먼트의 크기를 미리 알아야 한다는 문제가 있었다. 하지만 그냥 NULL을 ::CreateStreamOnHGlobal()에 넘겨주면 알아서 메모리를 할당하므로 크기를 알아올 필요가 없어져서 좋다. 내부 버퍼를 알아올라면 ::GetHGlobalFromStream()을 쓰면 된다.
MSDN 어딘가를 뒤져보며 있는데 위치를 까먹었다. ㅠㅠ
// 웹브라우저 컨트롤에서 가져화서 설정한다.
// 설정하는 방법은 다른데서 설명하기로 하자.
IHTMLDocument pDoc;
IStream * pStream = NULL;
IPersistStreamInit * pPSI = NULL;
HGLOBAL hHTMLContent;
HRESULT hr;
bool bResult = false;
BYTE* buff = NULL; // 여기다 소스를 담는다
hr = ::CreateStreamOnHGlobal(NULL, TRUE, &pStream);
if (SUCCEEDED(hr))
{
// request the IPersistStreamInit interface
hr = pDoc->QueryInterface(IID_IPersistStreamInit, (void **) &pPSI);
if (SUCCEEDED(hr))
{
hr = pPSI->Save(pStream, FALSE);
if (SUCCEEDED(hr))
{
hr = ::GetHGlobalFromStream(pStream, &hHTMLContent);
if (SUCCEEDED(hr))
{
bResult = true;
LPVOID data = ::GlobalLock(hHTMLContent);
DWORD size = ::GlobalSize(hHTMLContent);
buff = new BYTE[size + 1];
::memcpy(buff, data, size);
buff[size] = '\0';
::GlobalUnlock(hHTMLContent);
}
}
pPSI->Release();
}
// implicitly calls ::GlobalFree to free the global memory
pStream->Release();
}
=======================================================================================================
[다른방법]
홈페이지 소스 가져오기
//웹페이지 소스 가져오기
IWebBrowser2* pBrowser2;
HRESULT hr;
hr=OleInitialize(NULL);
if(!SUCCEEDED(hr))
return FALSE;
CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, (LPVOID *)&pBrowser2);
BSTR bstrURL = SysAllocString(L"http://news.naver.com/sports/new/main/index.nhn");
if(pBrowser2)
{
VARIANT vEmpty;
VariantInit(&vEmpty);
hr = pBrowser2->Navigate(bstrURL, &vEmpty, &vEmpty, &vEmpty, &vEmpty);
}
IHTMLDocument2* pHTMLDocument2;
LPDISPATCH lpDispatch;
pBrowser2->get_Document(&lpDispatch);
CString szSource = "";
if (lpDispatch)
{
HRESULT hr;
hr = lpDispatch->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&pHTMLDocument2);
lpDispatch->Release();
IHTMLElement* pBody;
hr = pHTMLDocument2->get_body(&pBody);
BSTR bstr;
pBody->get_innerHTML(&bstr);
int nLen;
char* szTarget;
nLen = (int)wcslen(bstr) * 2 + 1;
szTarget = new char[nLen];
::WideCharToMultiByte(CP_ACP, 0, bstr, -1, szTarget, nLen, NULL, NULL );
szSource.Format("%s", szTarget);
SysFreeString(bstr);
pBody->Release();
delete szTarget;
}
pBrowser2->Quit();
SysFreeString(bstrURL);
pBrowser2->Release();
OleUninitialize();
'개발지식창고 > ActiveX' 카테고리의 다른 글
Ctrl+c, Ctrl+v 처리 (0) | 2010.11.23 |
---|---|
다이얼로그 베이스에서 ATL 변수사용하기 (0) | 2010.10.19 |
웹브라우저 내에서의 TAB,ENTER 안먹히는부분 (0) | 2010.10.13 |
FindElement (0) | 2010.09.12 |
익스플로러 현재 모든 url 가져오기 (0) | 2010.09.08 |