まずはじめに、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_PAINTとWM_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スタイルとほぼ同等です。
|