#include <atlbase.h>
extern CComModule _Module; // ATLを使うためのお呪い
#include <atlcom.h>
#include <atlhost.h>
#include <exdispid.H>
#include <exdisp.h>
#include <mshtmcid.h>
#include <mshtml.h>
#include <windows.h>
#include <tchar.h>
#include <assert.h>
// ATLを使うためのお呪い
CComModule _Module;
BEGIN_OBJECT_MAP(ObjectMap)
END_OBJECT_MAP()
// カスタムブラウザアプリケーション用ウィンドウクラス
class AtBrowserClass {
static const TCHAR WINDOW_CLASS_NAME[];
AtBrowserClass(const AtBrowserClass&);
AtBrowserClass& operator=(const AtBrowserClass&);
public:
AtBrowserClass(LRESULT (CALLBACK* windowProcedure)(HWND, UINT, WPARAM, LPARAM));
HWND createWindow(LPCTSTR windowName, DWORD style,
int x, int y, int width, int height,
HWND parentWinodw, HMENU menu, HINSTANCE instance, LPVOID param) const;
};
// ウィンドウクラスの名前
const TCHAR AtBrowserClass::WINDOW_CLASS_NAME[] = _T("AtBrowser");
// AtBrowserClassのコンストラクタ
AtBrowserClass::AtBrowserClass(LRESULT (CALLBACK* windowProcedure)(HWND, UINT, WPARAM, LPARAM))
{
// ウィンドウクラスを登録する
WNDCLASSEX windowClass = {
sizeof(WNDCLASSEX),
CS_HREDRAW | CS_VREDRAW,
windowProcedure,
0,
0,
GetModuleHandle(NULL),
LoadIcon(NULL, IDI_APPLICATION),
LoadCursor(NULL, IDC_ARROW),
reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)),
NULL,
WINDOW_CLASS_NAME,
LoadIcon(NULL, IDI_APPLICATION),
};
RegisterClassEx(&windowClass);
}
HWND AtBrowserClass::createWindow(LPCTSTR windowName, DWORD style,
int x, int y, int width, int height,
HWND parentWinodw, HMENU menu,
HINSTANCE instance, LPVOID param) const
{
// ウィンドウクラスに属するウィンドウを作成する
return CreateWindow(WINDOW_CLASS_NAME, windowName, style,
x, y, width, height,
parentWinodw, menu, instance, param);
}
// カスタムブラウザ クラス
#define SINKID_ATBROWSER 0
class ATL_NO_VTABLE AtBrowser : public CComObjectRootEx<CComSingleThreadModel>
, public IDispEventImpl<SINKID_ATBROWSER, AtBrowser, &DIID_DWebBrowserEvents2> {
BEGIN_COM_MAP(AtBrowser)
COM_INTERFACE_ENTRY_IID(DIID_DWebBrowserEvents2, AtBrowser)
END_COM_MAP()
BEGIN_SINK_MAP(AtBrowser)
END_SINK_MAP()
HWND appWindow_; // アプリケーションウィンドウ
HWND ieWindow_; // ブラウザコンポーネントのコンテナウィンドウ
CComQIPtr<IWebBrowser2> browser_; // IEコンポーネント
AtBrowser(const AtBrowser&);
AtBrowser& operator=(const AtBrowser&);
public:
AtBrowser();
bool show(int commandShow);
int messageLoop();
private:
LRESULT onKeyDown(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT onDestroy(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK windowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
static const AtBrowserClass AT_BROWSER_CLASS;
};
// カスタムブラウザアプリケーション用ウィンドウクラスのインスタンスを生成する
const AtBrowserClass AtBrowser::AT_BROWSER_CLASS(&AtBrowser::windowProcedure);
// AtBrowserのコンストラクタ
AtBrowser::AtBrowser()
: appWindow_(NULL)
, ieWindow_(NULL)
, browser_()
{
// AtBrowserClassのインスタンスとして、アプリケーションウィンドウを作成する
// ウィンドウプロシージャはAtBrowser::windowProcedureが使われる
appWindow_ = AT_BROWSER_CLASS.createWindow(_T("AtBrowser"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, GetModuleHandle(NULL), NULL);
// AtWindowオブジェクトへの参照をウィンドウの属性として設定する (see AtBrowser::windowProcedure)
SetWindowLong(appWindow_, GWL_USERDATA, reinterpret_cast<LONG>(this));
// IEコンポーネントのコンテナとしてウィンドウを作成する
ieWindow_ = CreateWindow(_T("AtlAxWin"), _T("Shell.Explorer.2"), WS_CHILD | WS_VISIBLE | WS_MAXIMIZE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
appWindow_, NULL, GetModuleHandle(NULL), NULL);
// IEコンポーネントのインスタンスを取得して、コンテナに関連づける
CComPtr<IUnknown> unkown;
if (AtlAxGetControl(ieWindow_, &unkown) == S_OK) {
browser_ = unkown;
}
if (browser_ == NULL) {
// 失敗したらメッセージループを抜ける (アプリケーションを終了する)
PostQuitMessage(0);
}
UpdateWindow(appWindow_);
}
// アプリケーションウィンドウを表示する
bool AtBrowser::show(int commandShow)
{
AtlGetObjectSourceInterface(browser_, &m_libid, &m_iid, &m_wMajorVerNum, &m_wMinorVerNum);
DispEventAdvise(browser_);
browser_->GoHome();
return ShowWindow(appWindow_, commandShow) != FALSE;
}
int AtBrowser::messageLoop()
{
// Win32アプリケーションのお約束として、メッセージループを回す
MSG msg;
BOOL isValidMessage;
while ((isValidMessage = GetMessage(&msg, NULL, 0, 0)) != 0 && isValidMessage != -1) {
if (msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) {
TCHAR className[256];
GetClassName(msg.hwnd, className, (sizeof className) - 1);
if (_tcscmp(className, _T("Internet Explorer_Server")) == 0) {
SendMessage(appWindow_, msg.message, msg.wParam, msg.lParam);
}
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
// AtWindowアプリケーションのウィンドウプロシージャ
LRESULT CALLBACK AtBrowser::windowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// AtWindowオブジェクトへの参照をウィンドウの属性として取得する (see AtBrowser constructor)
AtBrowser* atBrowser = reinterpret_cast<AtBrowser*>(GetWindowLong(hwnd, GWL_USERDATA));
// ウィンドウメッセージに応じてディスパッチする
switch (message) {
case WM_KEYDOWN:
assert(atBrowser != NULL);
return atBrowser->onKeyDown(hwnd, message, wParam, lParam);
case WM_DESTROY :
assert(atBrowser != NULL);
return atBrowser->onDestroy(hwnd, message, wParam, lParam);
}
// ほとんどのメッセージはデフォルト処理に任せる
return DefWindowProc(hwnd, message, wParam, lParam);
}
// WM_KEYDOWNメッセージのハンドラ
LRESULT AtBrowser::onKeyDown(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
CComQIPtr<IOleInPlaceActiveObject, &IID_IOleInPlaceActiveObject> inPlace(browser_);
if (inPlace != NULL) {
MSG msg = {hwnd, message, wParam, lParam};
inPlace->TranslateAccelerator(&msg);
}
return 0;
}
// WM_DESTROYメッセージのハンドラ
LRESULT AtBrowser::onDestroy(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// アプリケーションウィンドウが閉じられたら、ブラウザオブジェクトを破棄してメッセージループを抜ける
browser_.Release();
PostQuitMessage(0);
return 0 ;
}
// エントリポイント / ここから実行が開始される
int APIENTRY _tWinMain(HINSTANCE instance, HINSTANCE previousInstance,
LPTSTR commandLine, int commandShow)
{
// ATLを使うためのお呪い
_Module.Init(ObjectMap, instance);
AtlAxWinInit();
// カスタムブラウザを実体化する
CComObject<AtBrowser>* atBrowser;
CComObject<AtBrowser>::CreateInstance(&atBrowser);
atBrowser->show(commandShow);
return atBrowser->messageLoop();
}
|