#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(); 
} 
  |