ホーム ATL/WTL
メッセージループ
ドキュメント種別 ATL/WTL に関する文書
最終更新日 2003/12/17
PR
 ATLだけを使って作成した「Hello, ATL/WTL」プログラムでは、メッセージループをSDKスタイルで書きました。

MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0){
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}
			

WTLには、メッセージループをカプセル化するためにCMessageLoopというクラスが用意されています。 ここでは、このCMessageLoopクラスを使って「Hello, ATL/WTL」プログラム書き換えます。 なお、今回からWTLのatlcrack.hヘッダで定義されているメッセージクラッカーを使用します。

// stdafx.h内
#include <atlbase.h>
#include <atlapp.h>
extern CAppModule _Module;  // CComModuleからCAppModuleに置き換える
#include <atlwin.h>

#include <atlcrack.h> // WTLメッセージクラッカーを使うため
			

// MainWindow.h内
class CMyWindow : public CWindowImpl<CMyWindow>
{
public:
    // ウィンドウクラス名を登録
    DECLARE_WND_CLASS(_T("Hello"));

private:
    // メッセージマップ
    BEGIN_MSG_MAP_EX(CMyWindow)
        MSG_WM_PAINT(OnPaint)
        MSG_WM_DESTROY(OnDestroy)
    END_MSG_MAP()

    void OnPaint(HDC /*hDC*/){
        PAINTSTRUCT ps;
        HDC hDC = BeginPaint(&ps);
        RECT rect;
        GetClientRect(&rect);
        DrawText(hDC, _T("Hello, ATL/WTL"),
            -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
        EndPaint(&ps);
    }

    void OnDestroy(){
        PostQuitMessage(0);
    }
};
			

// hello.cpp内
#include "stdafx.h"

#include "MainWindow.h"

CAppModule _Module;  // CComModuleからCAppModuleに置き換える

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR lpCmdLine, int nCmdShow)
{
    _Module.Init(NULL, hInstance);

    CMessageLoop theLoop;
    _Module.AddMessageLoop(&theLoop);

    // 独自ウィンドウを作成
    CMyWindow wnd;
    wnd.Create(NULL, CWindow::rcDefault,
        _T("Hello, ATL/WTL"), WS_OVERLAPPEDWINDOW | WS_VISIBLE);

    int nRet = theLoop.Run();

    _Module.RemoveMessageLoop();

    _Module.Term();

    return nRet;
}
			

 まず、stdafx.h内では、CMessageLoopクラスを使用するためにatlapp.hヘッダをインクルードします。 また、CMessageLoopクラスはCAppModuleクラスによって管理されるため、 これまで記述してきたCComModuleクラスをCAppModuleクラスに置き換えます。 CAppModuleクラスもatlapp.hヘッダに宣言されているため、CAppModuleクラスを 使用する前にatlapp.hヘッダをインクルードします。 さらにWTLのメッセージクラッカーを使用するために、atlcrack.hヘッダをインクルードしています。

 CMyWindowクラスでは、メッセージとメッセージハンドラを結びつけるために、 WTLのメッセージクラッカーを使用しています。本ドキュメントではATL3.0を使用しているため、 BEGIN_MSG_MAPBEGIN_MSG_MAP_EXに置き換えています。

 _tWinMain()内では、CMessageLoopクラスのインスタンスを作成し、 それをCAppModule::AddMessageLoop()CAppModule内部のマップに追加しています。 メッセージループはCMessageLoop::Run()によって実行され、必要なくなった メッセージループはCAppModule::RemoveMessageLoop()によって CAppModule内部のマップから削除します。

 このようにWTLでは、CMessageLoopクラスによってカプセル化されたメッセージループを、 CAppModuleクラスによって管理しています。 CAppModuleクラスの内部では、メッセージループとカレントスレッドIDをセットにしてマップに登録しています。 つまり、グローバル宣言されたCAppModuleクラスのインスタンスである_Moduleは、 複数のスレッド内にあるメッセージループを一元管理することになります。