Click here to visit our sponsor

ActiveX Control をホストするコンテナの作成 (ATL篇)


ATL でコントロールを使う

ATL が用意している コンテナクラス(CAxHostWindow) を利用します。


目次


ウイザードでプロジェクトの作成

ウイザードで SDK プロジェクト を作ってください。

次に StdAfx.h にヘッダーのインクルードをします。


クラスの作成

次にウインドウクラスを作ります。
(CMainWindow という名前にします / エラー処理は記述してません)

class CMainWindow : public CWindowImpl<CMainWindow, CWindow, CFrameWinTraits>
{
    CAxWindow m_ax;
    CComPtr<IUnknown> m_spUnknown;
public:
    CMainWindow() {}
    virtual ~CMainWindow() {}

BEGIN_MSG_MAP(CMainWindow)
    MESSAGE_HANDLER(WM_CREATE, OnCreate)
    MESSAGE_HANDLER(WM_SIZE, OnSize)
    MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
    MESSAGE_HANDLER(WM_CLOSE, OnClose)
END_MSG_MAP()

    LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        RECT rect;

        GetClientRect(&rect);
        AtlAxWinInit();

        m_ax.Create(m_hWnd, rect,
            _T("{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"),
            WS_CHILD|WS_VISIBLE);
        m_ax.QueryControl(&m_spUnknown);

        return 1;
    }
    LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        RECT rect = { 0, 0, LOWORD(lParam), HIWORD(lParam) };
        return m_ax.MoveWindow(&rect);
    }
    LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        DestroyWindow();
        return 0;
    }
    LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        m_spUnknown.Release();
        ::PostQuitMessage(0);
        return 0;
    }
};

Create() の 3番目の引数は、CLSID または ProgID の文字列です。
m_spUnknown は、コントロールのインターフェイスを得るためのもの。
OnDestroy()m_spUnknown.Release() を明示的に行っているのは、
WinMain()::CoUninitialize() より先に実行させるためです。


WinMain を作って完了

あとは、WinMain()

CComModule _Module;

int APIENTRY    WinMain(
    HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    ::CoInitialize(NULL);   // STA
    _Module.Init(0, hInstance);

    CMainWindow wndMain;
    wndMain.Create(0, CWindow::rcDefault, _T("Main"), 0, 0, NULL);
    wndMain.ShowWindow(nCmdShow);
    wndMain.UpdateWindow();

    MSG msg;

    while (::GetMessage(&msg, NULL, 0, 0)) {
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
    }
    _Module.Term();
    ::CoUninitialize();
    return 0;
}

これで、おしまい。


イベントの受信

IDispEventImpl をクラスに追加し、イベントハンドラの実装します。

#define UNIT_ID 1

class CMainWindow :
    public CWindowImpl<CMainWindow, CWindow, CFrameWinTraits>,
    public IDispEventImpl<UNIT_ID, CMainWindow, &DIID_DxxxxEvents>
{
BEGIN_SINK_MAP(CMainWindow)
    SINK_ENTRY(UNIT_ID, DIID_DxxxxEvents, DISPID, OnXxxxEvent)
END_SINK_MAP()

    void __stdcall OnXxxxEvent() { ... }
};

あとは、接続と切り離しを見合った場所で実行させます。

AtlAdviseSinkMap(this, TRUE or FALSE);

ただし、この方法は実装するクラスが CWindow の派生クラスである場合です。

CWindow を使わない場合、

IDispEventImplIDispEventSimpleImpl
SINK_ENTRYSINK_ENTRY_EX 又は SINK_ENTRY_INFO
AtlAdviseSinkMap()DispEventAdvise(), DispEventUnadvise()

を使います。


おわりに

このページの満足度は・・・

素晴らしい!
まあまあ、良いかも
自己満足感がよくわかるページですね
まったくもって説明不足


Visual C++ページトップ

HOME

兄弟ページ 姉妹ページ
Click here to visit our sponsor