ペインコンテナ
ペインコンテナとは、Explorerの左ペインのような外観を持つ、ビューウィンドウのコンテナのことです。ペインコンテナにの上部にはタイトル文字列を設定することができ、右上にはペインコンテナウィンドウを閉じるためのボタンが付いています。WTLはペインコンテナを作成するためにCPaneContainerを用意しています。

次に示すのは、先ほどマルチペインステータスバーを追加したプログラムの左ペインに、ペインコンテナを適用した例です。変更するのはCMainFrame内です。
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) 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_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); // スプリッタウィンドウを作成 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_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 OnFileExit(UINT uNotifyCode, int nID, HWND hWndCtl){ PostMessage(WM_CLOSE); } };
まず、CMainFrameクラス内でCPaneContainerのインスタンスをメンバ変数に追加します。CMainFrameクラスのWM_CREATEメッセージハンドラでは、まず、スプリッタウィンドウを親としてペインコンテナを作成します。この時、Create()の第1引数には親ウィンドウハンドル、第2引数にはペインコンテナに表示するタイトル文字列を指定します。なお、第2引数は文字列リソースIDでもかまいません。このほか、Create()にはウィンドウスタイル、拡張ウィンドウスタイル、ウィンドウ識別子、CREATESTRUCT構造体に含まれているウィンドウ作成データへのポインタを指定できます。
なお、SetPaneContainerExtendedStyle()を呼び出すとペインコンテナ拡張スタイルを設定することができます。次のスタイルが指定できます。
| 拡張スタイル | 説明 |
PANECNT_NOCLOSEBUTTON | ペインコンテナの右上の[閉じる]ボタンを非表示 |
PANECNT_VERTICAL | ペインコンテナのヘッダ(タイトルが表示される部分)を垂直に表示 |
次に、ペインコンテナを親として左ペインのビューウィンドウを作成し、そのビューウィンドウのハンドルをSetClientを呼び出してペインコンテナにセットします。さらにそのペインコンテナをSetSplitterPane()によってスプリッタウィンドウの左ペインにセットします。
このように、ビューウィンドウの親はペインコンテナであり、ペインコンテナの親はスプリッタウィンドウであり、スプリッタウィンドウの親はフレームウィンドウです。次に示すのはWTLのスプリッタウィンドウとペインコンテナを使ったアプリケーションのイメージ図です。

最後に、ペインコンテナの右上にある[閉じる]ボタンを押したときの処理を追加します。このボタンを押すとIDがID_PANE_CLOSEのコマンドメッセージが発生するため、CMainFrameクラスのメッセージマップにエントリを追加してOnMenuChangeView()を呼び出しています。この関数は以前作成したもので、ビューの表示を切り換えます。
ところで、ペインコンテナのメッセージマップにも、スプリッタウィンドウの場合と同様にFORWARD_NOTIFICATIONS()がエントリされています。このため、ビューウィンドウで発生したコマンドメッセージや通知メッセージは、その親であるペインコンテナへ送られ、さらにスプリッタウィンドウへ転送され、最後にフレームウィンドウへ届きます。

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_APP_EXIT, OnFileExit)
CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)
CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
END_MSG_MAP()
LRESULT OnCreate(LPCREATESTRUCT lpcs){