SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

ATL/WTLを利用したVisual C++のWindowsプログラミング

ATL/WTLプログラミング 6:ズームスクロールウィンドウ

ATL/WTLを利用したVisual C++のWindowsプログラミング

ズームスクロールウィンドウ

 ズームスクロールウィンドウとは、ズームイン/ズームアウト機能を備えたスクロールウィンドウのことです。WTLはズームスクロールウィンドウを作成するためにCZoomScrollWindowImplを用意しています。

 次に示すのは、先ほどペインコンテナを追加したプログラムの右ペインを、ズームスクロールウィンドウに変更した例です。メニューで[ズームイン](または[ズームアウト])を選択してビューウィンドウをクリックすると、フォントがズームイン(またはズームアウト)表示されます。

ズームイン前
ズームイン前
ズームイン後
ズームイン後
stdafx.h
#include <atlbase.h>
#include <atlapp.h>
extern CAppModule _Module;
#include <atlwin.h>

#include <atlcrack.h>
#include <atlmisc.h>
#include <atlctrls.h>
#include <atlctrlx.h>
#include <atlctrlw.h>
#include <atlframe.h>
#include <atlsplit.h>
#include <atlscrl.h>   // CZoomScrollWindowImplを使用するため
FontPreviewView.h
class CFontPreviewView : public CZoomScrollWindowImpl<CFontPreviewView>
{
    CString m_strFontName;

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

    // メッセージマップ
    BEGIN_MSG_MAP_EX(CFontPreviewView)
        MSG_WM_CREATE(OnCreate)
        CHAIN_MSG_MAP(CZoomScrollWindowImpl<CFontPreviewView>)
    END_MSG_MAP()

    LRESULT OnCreate(LPCREATESTRUCT lpcs){
        LRESULT lRet = DefWindowProc();

        SetScrollSize(640, 480);
        SetScrollLine(10, 10);
        SetScrollPage(100, 100);

        SetMsgHandled(false);

        return lRet;
    }

    void DoPaint(CDCHandle dc){
        // サイズ20ポイントのフォントを作成し、選択
        CFont font;
        font.CreatePointFont(200, m_strFontName);
        HFONT hOldFont = dc.SelectFont(font);

        // ビューウィンドウにフォント名を描画
        CSize size;
        GetScrollSize(size);
        CRect rect(0, 0, size.cx, size.cy);
        dc.DrawText(m_strFontName, -1,
            rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);

        // 元のフォントを選択
        dc.SelectFont(hOldFont);
    }

    void SetFontName(LPCTSTR lpszFontName){
        m_strFontName = lpszFontName;
        Invalidate();
    }
};
mainfrm.h
class CMainFrame : public CFrameWindowImpl<CMainFrame>,
        public CUpdateUI<CMainFrame>,
        public CMessageFilter, public CIdleHandler
{
public:
    DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME)

    CSplitterWindow  m_wndSplitter;      // スプリッタウィンドウ
    CPaneContainer m_painContainer;      // ペインコンテナ
    CFontListView m_viewFontList;        // 左ペイン
    CFontPreviewView m_viewFontPreview;  // 右ペイン

    CCommandBarCtrl m_CmdBar;                // コマンドバー
    CMultiPaneStatusBarCtrl m_wndStatusBar;  // マルチステータスバー

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

        // 左ペインのPreTranslateMessageを呼び出す
        if(m_viewFontList.PreTranslateMessage(pMsg))
            return TRUE;

        // 右ペインのPreTranslateMessageを呼び出す
        return m_viewFontPreview.PreTranslateMessage(pMsg);
    }

    virtual BOOL OnIdle(){
        UIUpdateToolBar();
        UIUpdateStatusBar();

        CString strCount;
        strCount.Format(_T("フォント数:%d"), m_viewFontList.GetCount());
        m_wndStatusBar.SetPaneText(IDS_PANE_COUNT, strCount);

        return FALSE;
    }

    BEGIN_UPDATE_UI_MAP(CMainFrame)
        UPDATE_ELEMENT(ID_MENUITEM_CHANGEVIEW, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
        UPDATE_ELEMENT(ID_MENUITEM_ZOOMIN, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
        UPDATE_ELEMENT(ID_MENUITEM_ZOOMOUT, UPDUI_MENUPOPUP | UPDUI_TOOLBAR)
    END_UPDATE_UI_MAP()

    BEGIN_MSG_MAP_EX(CMainFrame)
        MSG_WM_CREATE(OnCreate)
        COMMAND_CODE_HANDLER_EX(LBN_SELCHANGE, OnListSelChange)
        COMMAND_ID_HANDLER_EX(ID_PANE_CLOSE, OnMenuChangeView)
        COMMAND_ID_HANDLER_EX(ID_MENUITEM_CHANGEVIEW, OnMenuChangeView)
        COMMAND_ID_HANDLER_EX(ID_MENUITEM_ZOOMIN, OnMenuZoomIn)
        COMMAND_ID_HANDLER_EX(ID_MENUITEM_ZOOMOUT, OnMenuZoomOut)
        COMMAND_ID_HANDLER_EX(ID_APP_EXIT, OnFileExit)
        CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)
        CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
    END_MSG_MAP()

    LRESULT OnCreate(LPCREATESTRUCT lpcs){
        // コマンドバーを作成
        HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault,
            NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);

        // コマンドバーに現在のメニューバーのアイテムと画像をセット
        m_CmdBar.AttachMenu(GetMenu());
        m_CmdBar.LoadImages(IDR_MAINFRAME);

        // メニューバーを削除
        SetMenu(NULL);

        // ツールバーを作成
        HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd,
            IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);

        // リバーを作成
        CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);

        // リバーのバンドにコマンドバーとツールバーを追加
        AddSimpleReBarBand(hWndCmdBar);
        AddSimpleReBarBand(hWndToolBar, NULL, TRUE);

        // ステータスバーを作成
        m_hWndStatusBar = m_wndStatusBar.Create(m_hWnd);
        int nPanes[] = {ID_DEFAULT_PANE, IDS_PANE_COUNT};
        m_wndStatusBar.SetPanes(nPanes, sizeof(nPanes)/sizeof(nPanes[0]));

        UIAddToolBar(hWndToolBar);
        UIAddStatusBar(m_hWndStatusBar);

        UISetCheck(ID_MENUITEM_CHANGEVIEW, 1);
        UISetCheck(ID_MENUITEM_ZOOMIN, 1);
        UISetCheck(ID_MENUITEM_ZOOMOUT, 0);

        // スプリッタウィンドウを作成
        m_wndSplitter.Create(m_hWnd, rcDefault, NULL,
            WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);

        // スプリッタウィンドウ拡張スタイルを設定
        m_wndSplitter.SetSplitterExtendedStyle(0);

        // ペインコンテナを作成
        m_painContainer.Create(m_wndSplitter, _T("フォント名"));

        // 左ペインのビューウィンドウを作成
        m_viewFontList.Create(m_painContainer, rcDefault, NULL,
            WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
            WS_VSCROLL | LBS_NOINTEGRALHEIGHT | LBS_NOTIFY |
            LBS_WANTKEYBOARDINPUT | LBS_SORT, WS_EX_CLIENTEDGE);

        m_painContainer.SetClient(m_viewFontList);
        m_wndSplitter.SetSplitterPane(SPLIT_PANE_LEFT, m_painContainer);

        // 右ペインのビューウィンドウを作成
        m_viewFontPreview.Create(m_wndSplitter, rcDefault, NULL,
            WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
            WS_EX_CLIENTEDGE);

        m_viewFontPreview.SetZoomMode(ZOOMMODE_IN);

        m_wndSplitter.SetSplitterPane(SPLIT_PANE_RIGHT, m_viewFontPreview);

        m_hWndClient = m_wndSplitter;
        UpdateLayout();

        // 分割バーの位置を設定
        m_wndSplitter.SetSplitterPos(120);

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

        return 0;
    }

    void OnListSelChange(UINT uNotifyCode, int nID, HWND hWndCtl){
        // 現在選択されているアイテムを取得
        int nIndex = m_viewFontList.GetCurSel();
        if(nIndex != LB_ERR){
            CString strText;
            m_viewFontList.GetText(nIndex, strText);

            // 取得した文字列を右ペインに設定
            m_viewFontPreview.SetFontName(strText);
        }
    }

    void OnMenuChangeView(UINT uNotifyCode, int nID, HWND hWndCtl){
        if(m_wndSplitter.GetSinglePaneMode() == SPLIT_PANE_RIGHT){
            // 両ペイン表示
            m_wndSplitter.SetSinglePaneMode(SPLIT_PANE_NONE);
            UISetCheck(ID_MENUITEM_CHANGEVIEW, 1);
        }else{
            // 右ペインのみ表示
            m_wndSplitter.SetSinglePaneMode(SPLIT_PANE_RIGHT);
            UISetCheck(ID_MENUITEM_CHANGEVIEW, 0);
        }
    }

    void OnMenuZoomIn(UINT uNotifyCode, int nID, HWND hWndCtl){
        m_viewFontPreview.SetZoomMode(ZOOMMODE_IN);
        UISetCheck(ID_MENUITEM_ZOOMIN, 1);
        UISetCheck(ID_MENUITEM_ZOOMOUT, 0);
    }

    void OnMenuZoomOut(UINT uNotifyCode, int nID, HWND hWndCtl){
        m_viewFontPreview.SetZoomMode(ZOOMMODE_OUT);
        UISetCheck(ID_MENUITEM_ZOOMIN, 0);
        UISetCheck(ID_MENUITEM_ZOOMOUT, 1);
    }

    void OnFileExit(UINT uNotifyCode, int nID, HWND hWndCtl){
        PostMessage(WM_CLOSE);
    }
};

 まず、CZoomScrollWindowImplを使用するために「stdafx.h」で「atlscrl.h」をインクルードします。

 次に、CFontPreviewViewクラスを変更します。CFontPreviewViewクラスの基底クラスをCZoomScrollWindowImplに変更し、メッセージマップにCZoomScrollWindowImplへのチェーンを追加します。

 WM_CREATEメッセージハンドラではスクロールサイズを設定し、DoPaint()でフォント名を描画します。DoPaint()CZoomScrollWindowImplのメンバ関数で、CZoomScrollWindowImpl内のWM_PAINTメッセージハンドラから呼び出されます。

 これでズーム機能を備えたビューウィンドウは完成です。CZoomScrollWindowImplでは、デフォルトで左クリックによって自動的にズームイン/ズームアウトするコードが含まれています。

 後はフレームウィンドウにズームイン/ズームアウトのメニューとツールボタンを追加し、そのハンドラ関数(OnMenuZoomIn()/OnMenuZoomOut())でSetZoomMode()を呼び出してズームモードを切り換えます。SetZoomMode()には次のズームモードを指定できます。

ズームモード
種類説明
ZOOMMODE_OFFズーム機能オフ(デフォルト)
ZOOMMODE_INズームイン
ZOOMMODE_OUTズームアウト

最後に

 本稿では、WTLのGUIクラスであるマルチペインステータスバー、ペインコンテナ、ズームスクロールウィンドウを使用しました。

参考資料

  1. Windows Template Library(WTL) 7.1
  2. Windows Template Library(WTL)
  3. WTL support list
  4. The Code Project

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
ATL/WTLを利用したVisual C++のWindowsプログラミング連載記事一覧

もっと読む

この記事の著者

So()

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/392 2006/05/26 00:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー