실행중인 인터넷 익스플로어 제어하기
이거, 간단치 않았던 작업이다. 열려있는 인터넷 익스플로어(이하 IE)를 제어해야 했다. 하다 보니, 이런걸 요청 받기도 하고 또, 겨우겨우 구현하기도 한다. 최단로(路)인지는 모르겠지만, 어쨌든 길은 길이다.
IE::_FindWindow(const TCHAR* tszSubWindowText)는 IE의 윈도우타이틀을 검색해서 핸들을 구한다. IE::Back()함수와 IE::Navigate()함수는 모두 윈도우 핸들을 찾기 위한 윈도우 타이틀을 인자로 요구하며, 각각, IE의 뒤로 가기와 URL이동을 구현한다.
이 코드는 oleacc.lib가 필요하며, Window XP에서 테스트 되었다.
class IE
{
public:
static void Back(const TCHAR* tszSubWindowText);
static void Navigate(const TCHAR* tszSubWindowText, const TCHAR* tszDestUrl);
private:
IE()
{}
// Find Explorer_Server Window - subfunction of _Findwindow()
static HWND _Find_Explorer_Server(HWND hParentWnd, HWND hChildWnd);
// Find IE Window
static HWND _FindWindow(const TCHAR* tszSubWindowText);
static HWND _FindWindowWithSubWindowText(const TCHAR* tszSubWindowText);
private:
static HWND m_hWnd;
};// class IE
HWND IE::_Find_Explorer_Server(HWND hParentWnd, HWND hChildWnd)
{
if (hParentWnd == 0 || hChildWnd == 0) return 0;
TCHAR tszClassName[1024] = {0, };
::GetClassName(hChildWnd, tszClassName, 1024);
if (tstring(tszClassName) == _T("Internet Explorer_Server")) return hChildWnd;
HWND hRetWnd = _Find_Explorer_Server(hChildWnd, ::FindWindowEx(hChildWnd, 0, 0, 0));
if (hRetWnd != 0) return hRetWnd;
return _Find_Explorer_Server(hParentWnd, ::FindWindowEx(hParentWnd, hChildWnd, 0, 0));
}
HWND IE::_FindWindow(const TCHAR* tszSubWindowText)
{
HWND hWnd = _FindWindowWithSubWindowText(tszSubWindowText);
return _Find_Explorer_Server(hWnd, ::FindWindowEx(hWnd, 0, 0, 0));
}
HWND IE::_FindWindowWithSubWindowText(const TCHAR* tszSubWindowText)
{
HWND hWnd = 0;
while (hWnd = ::FindWindowEx(0, hWnd, _T("IEFrame"), 0))
{
TCHAR tszWindowText[1024] = {0, };
::GetWindowText(hWnd, tszWindowText, 1024);
size_t pos = tstring(tszWindowText).find(tszSubWindowText);
if (pos != tstring::npos) return hWnd;
}
return 0;
}
void IE::Back(const TCHAR* tszSubWindowText)
{
m_hWnd = _FindWindowWithSubWindowText(tszSubWindowText);
if (m_hWnd)
{
::SetForegroundWindow(m_hWnd);
m_hWnd = _FindWindow(tszSubWindowText);
HRESULT hr;
if (FAILED(hr = CoInitialize(NULL))) return;
LRESULT lRes;
UINT nMsg = ::RegisterWindowMessage(_T("WM_HTML_GETOBJECT"));
::SendMessageTimeout(m_hWnd, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes);
CComPtr<IHTMLDocument2> spDoc;
CComPtr<IHTMLWindow2> spWnd2;
CComPtr<IServiceProvider> spServiceProv;
hr = ::ObjectFromLresult(lRes, IID_IHTMLDocument2, 0, (void**)&spDoc);
if (SUCCEEDED(hr))
{
hr = spDoc->get_parentWindow((IHTMLWindow2**)&spWnd2);
if (SUCCEEDED(hr))
{
hr = spWnd2->QueryInterface(IID_IServiceProvider, (void**)&spServiceProv);
if (SUCCEEDED(hr))
{
IWebBrowser2* pWebBrowser2 = 0;
hr = spServiceProv->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&pWebBrowser2);
hr = pWebBrowser2->GoBack();
pWebBrowser2->Release();
spServiceProv.Release();
}
spWnd2.Release();
}
spDoc.Release();
}
CoUninitialize();
}
}
void IE::Navigate(const TCHAR* tszSubWindowText, const TCHAR* tszDestUrl)
{
m_hWnd = _FindWindowWithSubWindowText(tszSubWindowText);
if (m_hWnd)
{
::SetForegroundWindow(m_hWnd);
m_hWnd = _FindWindow(tszSubWindowText);
HRESULT hr;
if (FAILED(hr = CoInitialize(NULL))) return;
LRESULT lRes;
UINT nMsg = ::RegisterWindowMessage(_T("WM_HTML_GETOBJECT"));
::SendMessageTimeout(m_hWnd, nMsg, 0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&lRes);
CComPtr<IHTMLDocument2> spDoc;
CComPtr<IHTMLWindow2> spWnd2;
CComPtr<IServiceProvider> spServiceProv;
hr = ::ObjectFromLresult(lRes, IID_IHTMLDocument2, 0, (void**)&spDoc);
if (SUCCEEDED(hr))
{
hr = spDoc->get_parentWindow((IHTMLWindow2**)&spWnd2);
if (SUCCEEDED(hr))
{
hr = spWnd2->QueryInterface(IID_IServiceProvider, (void**)&spServiceProv);
if (SUCCEEDED(hr))
{
IWebBrowser2* pWebBrowser2 = 0;
hr = spServiceProv->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&pWebBrowser2);
CComVariant v;
CComBSTR url(tszDestUrl);
hr = pWebBrowser2->Navigate(url, &v, &v, &v, &v);
pWebBrowser2->Release();
spServiceProv.Release();
}
spWnd2.Release();
}
spDoc.Release();
}
CoUninitialize();
}
}
근데…, 이걸 어디에 쓰냐고?
쓸 데가 있더이다~