ホーム WTL Mobile
エディット
ドキュメント種別 ATL/WTL に関する文書
最終更新日 2010/02/10
PR
 以下に示すのは、エディットコントロールをベースとしたビューウィンドウを作成する例です。 プロジェクトにView.hというヘッダファイルを追加し、そこにCEditViewというクラスを定義します。 ビューウィンドウのフォントは10ポイントサイズのMSゴシックに設定します。


// View.h
#pragma once

class CEditView : public CWindowImpl<CEditView, CEdit>
{
public:
    DECLARE_WND_SUPERCLASS(NULL, CEdit::GetWndClassName())

    CFont m_font;

    BOOL PreTranslateMessage(MSG* pMsg){
        return FALSE;
    }

    BEGIN_MSG_MAP(CEditView)
        MSG_WM_CREATE(OnCreate)
    END_MSG_MAP()

    int OnCreate(LPCREATESTRUCT lpCreateStruct){
        LRESULT lRet = DefWindowProc();

        // フォント設定
        m_font.CreatePointFont(100, _T("MS ゴシック"));
        SetFont(m_font);

        return lRet;
    }
};
			

CEditViewクラスはCWindowImplから派生し、 CWindowImplの第2テンプレート引数には、ベースとなるCEditクラスを指定します。 WM_CREATEメッセージハンドラでは、 SetFont()を呼び出してフォントを10ポイントサイズのMSゴシックに設定します。

 次に示すのは、CEditViewクラスを使用する例です。

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

#define WINVER 0x0420
#include <atlbase.h>
#if _ATL_VER == 0x900
#define _SECURE_ATL 1
#endif

#define _WTL_USE_CSTRING
#include <atlapp.h>
extern CAppModule _Module;
#include <atlwin.h>

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

#include <atlcrack.h>
#include <atlmisc.h>
#include <atlframe.h>
#include <atlctrls.h>
#define _WTL_CE_NO_ZOOMSCROLL
#define _WTL_CE_NO_FULLSCREEN
#include <atlwince.h>
			

// SampleProjectFrame.h
#pragma once

class CSampleProjectFrame : 
    public CFrameWindowImpl<CSampleProjectFrame>,
    public CUpdateUI<CSampleProjectFrame>,
    public CAppWindow<CSampleProjectFrame>,
    public CMessageFilter, public CIdleHandler
{
public:
    DECLARE_APP_FRAME_CLASS(NULL, IDR_MAINFRAME, L"Software\\WTL")

    CEditView m_view;

    virtual BOOL PreTranslateMessage(MSG* pMsg){
        if(CFrameWindowImpl<CSampleProjectFrame>::PreTranslateMessage(pMsg))
            return TRUE;

        return m_view.IsWindow() ? m_view.PreTranslateMessage(pMsg) : FALSE;
    }

    virtual BOOL OnIdle(){
        return FALSE;
    }

    BEGIN_UPDATE_UI_MAP(CSampleProjectFrame)
    END_UPDATE_UI_MAP()

    BEGIN_MSG_MAP(CSampleProjectFrame)
        MSG_WM_CREATE(OnCreate)
        MSG_WM_DESTROY(OnDestroy)
        CHAIN_MSG_MAP(CAppWindow<CSampleProjectFrame>)
        CHAIN_MSG_MAP(CUpdateUI<CSampleProjectFrame>)
        CHAIN_MSG_MAP(CFrameWindowImpl<CSampleProjectFrame>)
    END_MSG_MAP()

    int OnCreate(LPCREATESTRUCT lpCreateStruct){
        // メニューバー作成
        CreateSimpleCEMenuBar(0, SHCMBF_EMPTYBAR);

        // ビューを作成
        m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL,
            WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | 
            WS_HSCROLL | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL |
            ES_MULTILINE | ES_NOHIDESEL
        );

        // メッセージループにメッセージフィルタとアイドルハンドラを追加
        CMessageLoop* pLoop = _Module.GetMessageLoop();
        pLoop->AddMessageFilter(this);
        pLoop->AddIdleHandler(this);
        return 0;
    }

    void OnDestroy(){
        // メッセージループからメッセージフィルタとアイドルハンドラを削除
        CMessageLoop* pLoop = _Module.GetMessageLoop();
        pLoop->RemoveMessageFilter(this);
        pLoop->RemoveIdleHandler(this);
        SetMsgHandled(false);
    }
};
			

// SampleProject.cpp
#include "stdafx.h"
#include "resourceppc.h"
#include "View.h"
#include "SampleProjectFrame.h"

CAppModule _Module;

int WINAPI _tWinMain(HINSTANCE hInstance,
    HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{
    HRESULT hRes =
        CSampleProjectFrame::ActivatePreviousInstance(hInstance, lpstrCmdLine);

    if(FAILED(hRes) || S_FALSE == hRes){
        return hRes;
    }

    hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
    ATLASSERT(SUCCEEDED(hRes));

    AtlInitCommonControls(ICC_DATE_CLASSES);
    SHInitExtraControls();

    hRes = _Module.Init(NULL, hInstance);
    ATLASSERT(SUCCEEDED(hRes));

    int nRet = CSampleProjectFrame::AppRun(lpstrCmdLine, nCmdShow);

    _Module.Term();
    ::CoUninitialize();

    return nRet;
}
			

 まず、CEditViewクラスのインスタンスを CSampleProjectFrameクラスのメンバ変数として宣言し、 WM_CREATEメッセージハンドラでCreate()を呼び出してビューウィンドウを作成します。

 最後に、SampleProject.cppファイルでSampleProjectFrame.hヘッダの前にView.hヘッダをインクルードします。

CEditCommands
 WTLのCEditCommandsクラステンプレートを使用すると、 エディットコントロールを操作する処理を簡略化できます。

 次に示すのは、CEditCommandsクラステンプレートを使用して、 先述のプログラムにメニューからエディットコントロールを操作する機能を追加する例です。 まず、CEditViewクラスを変更します。

// View.h
#pragma once

class CEditView : public CWindowImpl<CEditView, CEdit>,
    public CEditCommands<CEditView>
{
public:
    DECLARE_WND_SUPERCLASS(NULL, CEdit::GetWndClassName())

    CFont m_font;

    BOOL PreTranslateMessage(MSG* pMsg){
        return FALSE;
    }

    BEGIN_MSG_MAP(CEditView)
        MSG_WM_CREATE(OnCreate)
        CHAIN_MSG_MAP_ALT(CEditCommands<CEditView>, 1)
    END_MSG_MAP()

    int OnCreate(LPCREATESTRUCT lpCreateStruct){
        LRESULT lRet = DefWindowProc();

        // フォント設定
        m_font.CreatePointFont(100, _T("MS ゴシック"));
        SetFont(m_font);

        return lRet;
    }
};
			

 まず、CEditViewクラスの基底クラスにCEditCommandsクラステンプレートを追加します。 CEditCommandsのテンプレート引数には、操作対象となるエディットコントロールのクラスを指定します。

次に、メッセージマップにCEditCommandsの代替メッセージマップへのチェインを追加します。 CEditCommandsは、デフォルトで以下のIDに対応したエディットコントロール用WM_COMMANDメッセージハンドラを用意しています。

ID 操作
ID_EDIT_CLEAR 削除
ID_EDIT_CLEAR_ALL すべて削除
ID_EDIT_COPY コピー
ID_EDIT_CUT 切り取り
ID_EDIT_PASTE 貼り付け
ID_EDIT_SELECT_ALL すべて選択
ID_EDIT_UNDO 元に戻す

 次に示すのは、変更したCEditViewクラスを使用する例です。

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

#define WINVER 0x0420
#include <atlbase.h>
#if _ATL_VER == 0x900
#define _SECURE_ATL 1
#endif

#define _WTL_USE_CSTRING
#include <atlapp.h>
extern CAppModule _Module;
#include <atlwin.h>

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

#include <atlcrack.h>
#include <atlmisc.h>
#include <atlframe.h>
#include <atlctrls.h>
#define _WTL_CE_NO_ZOOMSCROLL
#define _WTL_CE_NO_FULLSCREEN
#include <atlwince.h>
			

// SampleProjectFrame.h
#pragma once

class CSampleProjectFrame : 
    public CFrameWindowImpl<CSampleProjectFrame>,
    public CUpdateUI<CSampleProjectFrame>,
    public CAppWindow<CSampleProjectFrame>,
    public CMessageFilter, public CIdleHandler
{
public:
    DECLARE_APP_FRAME_CLASS(NULL, IDR_MAINFRAME, L"Software\\WTL")

    CEditView m_view;

    virtual BOOL PreTranslateMessage(MSG* pMsg){
        if(CFrameWindowImpl<CSampleProjectFrame>::PreTranslateMessage(pMsg))
            return TRUE;

        return m_view.IsWindow() ? m_view.PreTranslateMessage(pMsg) : FALSE;
    }

    virtual BOOL OnIdle(){
        UIEnable(ID_EDIT_UNDO, m_view.CanUndo());
        UIEnable(ID_EDIT_CUT, m_view.CanCut());
        UIEnable(ID_EDIT_COPY, m_view.CanCopy());
        UIEnable(ID_EDIT_CLEAR, m_view.CanClear());
        return FALSE;
    }

    BEGIN_UPDATE_UI_MAP(CSampleProjectFrame)
        UPDATE_ELEMENT(ID_EDIT_UNDO, UPDUI_MENUPOPUP)
        UPDATE_ELEMENT(ID_EDIT_CUT, UPDUI_MENUPOPUP)
        UPDATE_ELEMENT(ID_EDIT_COPY, UPDUI_MENUPOPUP)
        UPDATE_ELEMENT(ID_EDIT_CLEAR, UPDUI_MENUPOPUP)
    END_UPDATE_UI_MAP()

    BEGIN_MSG_MAP(CSampleProjectFrame)
        MSG_WM_CREATE(OnCreate)
        MSG_WM_DESTROY(OnDestroy)
        COMMAND_ID_HANDLER_EX(ID_APP_EXIT, OnAppExit)
        CHAIN_MSG_MAP(CAppWindow<CSampleProjectFrame>)
        CHAIN_MSG_MAP(CUpdateUI<CSampleProjectFrame>)
        CHAIN_MSG_MAP(CFrameWindowImpl<CSampleProjectFrame>)
        CHAIN_CLIENT_COMMANDS()    // ビュークラスへコマンドチェイン
    END_MSG_MAP()

    int OnCreate(LPCREATESTRUCT lpCreateStruct){
        // メニューバー作成
        CreateSimpleCEMenuBar(IDR_MAINFRAME, SHCMBF_HMENU);

        // ビューを作成
        m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL,
            WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | 
            WS_HSCROLL | WS_VSCROLL | ES_AUTOHSCROLL | ES_AUTOVSCROLL |
            ES_MULTILINE | ES_NOHIDESEL
        );

        // メッセージループにメッセージフィルタとアイドルハンドラを追加
        CMessageLoop* pLoop = _Module.GetMessageLoop();
        pLoop->AddMessageFilter(this);
        pLoop->AddIdleHandler(this);
        return 0;
    }

    void OnDestroy(){
        // メッセージループからメッセージフィルタとアイドルハンドラを削除
        CMessageLoop* pLoop = _Module.GetMessageLoop();
        pLoop->RemoveMessageFilter(this);
        pLoop->RemoveIdleHandler(this);
        SetMsgHandled(false);
    }

    void OnAppExit(UINT uNotifyCode, int nID, CWindow wndCtl){
        PostMessage(WM_CLOSE);
    }
};
			

// SampleProject.cpp
#include "stdafx.h"
#include "resourceppc.h"
#include "View.h"
#include "SampleProjectFrame.h"

CAppModule _Module;

int WINAPI _tWinMain(HINSTANCE hInstance,
    HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{
    HRESULT hRes =
        CSampleProjectFrame::ActivatePreviousInstance(hInstance, lpstrCmdLine);

    if(FAILED(hRes) || S_FALSE == hRes){
        return hRes;
    }

    hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
    ATLASSERT(SUCCEEDED(hRes));

    AtlInitCommonControls(ICC_DATE_CLASSES);
    SHInitExtraControls();

    hRes = _Module.Init(NULL, hInstance);
    ATLASSERT(SUCCEEDED(hRes));

    int nRet = CSampleProjectFrame::AppRun(lpstrCmdLine, nCmdShow);

    _Module.Term();
    ::CoUninitialize();

    return nRet;
}
			

 まず、プロジェクトにメニューリソースを追加し、[ID]と[Caption]を次のように設定します。

リソース名 ID Caption
メニュー IDR_MAINFRAME -
メニューアイテム(トップレベル) ID_APP_EXIT 終了
メニューアイテム(トップレベル) - 編集
メニューアイテム ID_EDIT_UNDO 元に戻す
メニューアイテム ID_EDIT_CUT 切り取り
メニューアイテム ID_EDIT_COPY コピー
メニューアイテム ID_EDIT_PASTE 貼り付け
メニューアイテム ID_EDIT_CLEAR 削除



 次に、CSampleProjectFrameクラスのメッセージマップにCHAIN_CLIENT_COMMANDS()マクロを追加し、 WM_CREATEメッセージハンドラでメニューバーを作成します。 これで、[編集]以下のメニューアイテムを実行すると、 コマンドチェインによってWM_COMMANDメッセージがフレームウィンドウからビューウィンドウへ転送され、 さらに代替メッセージマップへのチェインによってCEditCommandsの代替メッセージマップに転送されます。 CEditCommandsでは、先述のようにエディットコントロール用WM_COMMANDメッセージハンドラが用意されているため、 そこでエディットコントロールを操作するための関数が呼び出されます。

 次に、CSampleProjectFrameクラスのUI更新ハンドラマップに ID_EDIT_UNDOID_EDIT_CUTID_EDIT_COPYID_EDIT_CLEAR用のエントリを追加し、 OnIdle()内でそれらに対するUIEnable()を呼び出します。 CEditCommandsは、 エディットコントロールのUI更新ハンドラ用に次のような関数を用意しています。

関数名 機能
CanCut エディットコントロールに選択された文字列があるかどうか
CanCopy エディットコントロールに選択された文字列があるかどうか
CanClear エディットコントロールに選択された文字列があるかどうか
CanSelectAll エディットコントロールに文字列があるかどうか
CanFind エディットコントロールに文字列があるかどうか
CanRepeat エディットコントロールに文字列があるかどうか
CanReplace エディットコントロールに文字列があるかどうか
CanClearAll エディットコントロールに文字列があるかどうか

CSampleProjectFrameクラスではアイドル時にこれらの関数でエディットコントロールの内容を調べ、 メニューアイテムの状態を更新します。