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

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

 CWindowでウィンドウを作成するには、Create()を呼び出したり、 既存のウィンドウハンドルをAttach()でアタッチする必要があります。

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

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


プロジェクトファイル ダウンロード
// stdafx.h
#pragma once

#define WINVER _WIN32_WCE

#include <atlbase.h>
#include <atlwin.h>

#include <aygshell.h>
#pragma comment(lib, "aygshell.lib") 
			

// MainWindow.h
#pragma once

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

    // メッセージマップ
    BEGIN_MSG_MAP(CMainWindow)
        MESSAGE_HANDLER(WM_PAINT, OnPaint)
        MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
        MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
        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 OnActivate(UINT, WPARAM, LPARAM, BOOL&){
        SHFullScreen(m_hWnd, SHFS_HIDESIPBUTTON);
        return 0;
    }

    LRESULT OnSettingChange(UINT, WPARAM, LPARAM, BOOL&){
        SHFullScreen(m_hWnd, SHFS_HIDESIPBUTTON);
        return 0;
    }

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

// SampleProject.cpp
#include "stdafx.h"
#include "MainWindow.h"

int APIENTRY _tWinMain(HINSTANCE hInstance, 
                       HINSTANCE hPrevInstance, 
                       LPTSTR    lpCmdLine, 
                       int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    TCHAR szAppName[] = _T("SampleProject");

    HWND hWnd = FindWindow(szAppName, szAppName);    
    if(hWnd){
        SetForegroundWindow((HWND)((ULONG) hWnd | 0x00000001));
        return 0;
    }

    CMainWindow wnd;
    wnd.Create(NULL, CWindow::rcDefault, szAppName, WS_OVERLAPPEDWINDOW | WS_VISIBLE);

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

    return (int)msg.wParam;
}
			

 まず、stdafx.hヘッダではATLを使用するためにatlbase.hヘッダとatlwin.hヘッダをインクルードします。 また、SHFullScreen()を使用するためにaygshell.hヘッダをインクルードし、aygshell.libをリンクします。

 CMainWindowクラスはCWindowImplクラステンプレートから派生していますが、CWindowImplの第1テンプレート引数にも CMainWindowという名前を渡します(第2、第3テンプレート引数は省略可能です。ここでは省略しています。)。 CMainWindowクラスでは、DECLARE_WND_CLASSマクロでウィンドウクラス名を登録します。 SDKスタイルの Windows Mobile プログラミングでは、 ウィンドウクラス名や背景色などの属性を指定するためにWNDCLASS構造体のメンバに値をセットしますが、 ATLにはその作業を単純化するためにDECLARE_WND_CLASSマクロを含め次のようなマクロが用意されています。

  • DECLARE_WND_CLASS(ウィンドウクラス名)
    ウィンドウクラス名のみを定義します。

  • DECLARE_WND_CLASS_EX(ウィンドウクラス名, スタイル, 背景色)
    ウィンドウクラス名、スタイル、背景色を定義します。

これらのマクロはpublic宣言で使用しなければなりません。 これらのマクロを使ってウィンドウクラス名を明示的に登録しなければ、ATLは "ATL:2c218" のような名前を自動的に 登録します。

 メッセージマップでは、メッセージとそれに対するハンドラ関数を結びつけます。 今回の例では、ハンドラ関数内の処理はSDKスタイルとほぼ同等です。 なお、WM_ACTIVATEメッセージハンドラ関数とWM_SETTINGCHANGEメッセージハンドラ関数では、 引数にSHFS_HIDESIPBUTTONを指定してSHFullScreen()を呼び出すことでSIPボタンを非表示にします。 もしSIPボタンを非表示にしなければ次のようになります。


 次に、_tWinMain()では、FindWindow()を呼び出してすでに同じプログラムが起動しているかどうかチェックします。 起動している場合は、SetForegroundWindow()を呼び出して起動済みのプログラムをフォアグラウンドに表示し、終了します。 これは、多重起動によるリソース消費を抑えるためです。 同じプログラムが起動していない場合は、通常のWindowsアプリケーションと同様にウィンドウを作成してメッセージループを実行します。