ホーム ATL/WTL
ウィンドウ
ドキュメント種別 ATL/WTL に関する文書
最終更新日 2003/12/17
PR
 まずはじめに、WTLを使わずにATLだけを使ってテンプレートライブラリによる Windowsプログラミングの基本を見てみたいと思います。

 ATLにおける最も基本的なウィンドウ関連クラスはCWindowです。 CWindowクラスはウィンドウハンドルをカプセル化し、ウィンドウに関するWin32APIをラップする 多くのメンバ関数を持ちます。これはちょうどMFCのCWndクラスと似ています。

 CWindowでウィンドウを作成するには、Createメンバ関数を使ったり、既存のウィンドウハンドルを Attachメンバ関数でアタッチする必要があります。

 ところで、CWindowクラスはメッセージへの反応を定義することはできません。 ここで、もしMFCならばCWndの派生クラスを作り、例えばWM_CREATEメッセージへの反応を 定義するためにはOnCreateをオーバーライドするところですが、 ATLでは、CWindowの派生クラスであるCWindowImplクラスから派生クラスを作り、そのクラス内で メッセージへの応答を定義します。

 以下の示すのは、ウィンドウ中央に「Hello, ATL/WTL」と表示するだけの簡単なプログラムのソースコードです。 このプログラムでは、CWindowImplクラスから派生クラスCMyWindow(これがメインウィンドウとなります)を作り、 CMyWindowクラス内でWM_PAINTWM_DESTROYメッセージへの応答を定義しています。 なお、このプログラムはWin32Applicationプロジェクトでビルドします。


// stdafx.h内
#include <atlbase.h>
extern CComModule _Module;
#include <atlwin.h>
			

// MainWindow.h内
// CWindowImplの派生クラスでメッセージへの反応を定義
class CMyWindow : public CWindowImpl<CMyWindow>
{
public:
    // ウィンドウクラス名を登録
    DECLARE_WND_CLASS(_T("Hello"));

private:
    // メッセージマップ
    BEGIN_MSG_MAP(CMyWindow)
        MESSAGE_HANDLER(WM_PAINT, OnPaint)
        MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
    END_MSG_MAP()

    LRESULT OnPaint(UINT, WPARAM, LPARAM, BOOL&){
        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);
        return 0;
    }

    LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL&){
        PostQuitMessage(0);
        return 0;
    }
};
			

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

CComModule _Module;

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

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

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

    _Module.Term();

    return msg.wParam;
}
			

 まず、ATLを使用するためのヘッダをインクルードしますが、CComModuleクラスのインスタンスである _ModuleはATLの各ヘッダから参照されるのでグローバルに宣言しておきます。 もっとも、ATL7.0以降を使用している場合はこのグローバル宣言は必要ないようです。 この_Moduleは、_tWinMain()の最初と最後で初期化と後始末をしています。

 CMyWindowクラスはCWindowImplクラスから派生していますが、CWindowImplの第1テンプレート引数にも CMyWindowという名前を渡します(第2、3テンプレート引数は省略可能です。ここでは省略しています。)。 CMyWindowクラス内では、ウィンドウクラス名をDECLARE_WND_CLASSマクロによって登録し、 メッセージマップによってメッセージとそれに対するハンドラを結びつけています。 今回の例では、ハンドラ内の処理はSDKスタイルとほぼ同等です。