ホーム ATL/WTL
タブ
ドキュメント種別 ATL/WTL に関する文書
最終更新日 2007/03/21
PR
 WTLではコモンコントロールのタブコントロールをCTabCtrlT というクラステンプレートでカプセル化しています。 テンプレート引数にはクラスを指定しますが、 そのクラスはCTabCtrlTの基底クラスとして使用されます。 atlctrls.hヘッダではtypedefによって次のように宣言されています。

// atlctrls.h
typedef CTabCtrlT<ATL::CWindow>   CTabCtrl;
			

これは、CTabCtrlクラスはCWindowクラスの派生クラスであることを意味します。

 WTLのCTabCtrlクラスは、MFCの同名のクラスとほぼ同じメンバ関数を用意しています。 以下に示すのは、CTabCtrlクラスを使用する例です。 一つ目のタブにはカレントディレクトリのファイル一覧を表示するリストビューコントロールを設定し、 二つ目のタブにはDLLのバージョン情報を表示するリストビューコントロールを設定します。



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

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

#include <atlcrack.h>
#include <atlmisc.h>
#include <atlctrls.h>  // コントロール用クラスを使用するため
			

// MainDlg.h
#pragma once

class CMainDlg : public CDialogImpl<CMainDlg>
{
public:
    enum { IDD = IDD_MAINDLG };

    CTabCtrl m_tab_display;     // タブ
    CListViewCtrl m_list_file;  // [ファイル]リストビュー
    CListViewCtrl m_list_info;  // [DLL情報]リストビュー

    BEGIN_MSG_MAP(CMainDlg)
        MSG_WM_INITDIALOG(OnInitDialog)
        NOTIFY_HANDLER_EX(IDC_TAB_DISPLAY, TCN_SELCHANGING, OnTabSelChanging)
        NOTIFY_HANDLER_EX(IDC_TAB_DISPLAY, TCN_SELCHANGE, OnTabSelChange)
        COMMAND_ID_HANDLER_EX(IDOK, OnOK)
        COMMAND_ID_HANDLER_EX(IDCANCEL, OnCancel)
    END_MSG_MAP()

    BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam){
        // スクリーンの中央に配置
        CenterWindow();

        // 大きいアイコン設定
        HICON hIcon = AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR,
            ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON));
        SetIcon(hIcon, TRUE);
        
        // 小さいアイコン設定
        HICON hIconSmall = AtlLoadIconImage(IDR_MAINFRAME, LR_DEFAULTCOLOR,
            ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON));
        SetIcon(hIconSmall, FALSE);

        // コントロール設定
        m_tab_display = GetDlgItem(IDC_TAB_DISPLAY);
        m_list_file = GetDlgItem(IDC_LIST_FILE);
        m_list_info = GetDlgItem(IDC_LIST_INFO);

        // タブコントロールの配置
        CRect rcClient;
        GetClientRect(rcClient);
        int nPaddingX = GetSystemMetrics(SM_CXDLGFRAME);
        int nPaddingY = GetSystemMetrics(SM_CYDLGFRAME);
        m_tab_display.SetWindowPos(HWND_BOTTOM,
            rcClient.left + nPaddingX, rcClient.top + nPaddingY, 
            rcClient.Width() - nPaddingX * 2, rcClient.Height() - nPaddingY * 2,
            SWP_SHOWWINDOW);

        // タブアイテム追加
        m_tab_display.AddItem(
            TCIF_TEXT | TCIF_PARAM, _T("ファイル"), 0, (DWORD)m_list_file.m_hWnd);
        m_tab_display.AddItem(
            TCIF_TEXT | TCIF_PARAM, _T("DLL情報"), 0, (DWORD)m_list_info.m_hWnd);

        // タブコントロールの表示領域取得
        CRect rcTabClient;
        m_tab_display.GetClientRect(rcTabClient);
        m_tab_display.AdjustRect(FALSE, rcTabClient);
        rcTabClient.OffsetRect(nPaddingX, nPaddingY);

        // [ファイル]リストビューコントロールの配置
        m_list_file.MoveWindow(rcTabClient);
        m_list_file.SetExtendedListViewStyle(LVS_EX_INFOTIP | LVS_EX_FULLROWSELECT);

        CRect rcList;
        m_list_file.GetWindowRect(rcList);
        int nScrollWidth = GetSystemMetrics(SM_CXVSCROLL);
        int n3DEdge = GetSystemMetrics(SM_CXEDGE);
        m_list_file.InsertColumn(0, _T("名前"), LVCFMT_LEFT,
            rcList.Width() - nScrollWidth - n3DEdge * 2, -1);

        CFindFile find;
        if(find.FindFile()){
            do{
                if(!find.IsDots() && !find.IsDirectory()){
                    int nIndex = m_list_file.GetItemCount();
                    m_list_file.AddItem(nIndex, 0, find.GetFileName());
                }
            }while(find.FindNextFile());
        }

        // [DLL情報]リストビューコントロールの配置
        m_list_info.MoveWindow(rcTabClient);
        m_list_info.SetExtendedListViewStyle(LVS_EX_INFOTIP | LVS_EX_FULLROWSELECT);

        m_list_info.InsertColumn(0, _T("DLL名"), LVCFMT_LEFT, 180, -1);
        m_list_info.InsertColumn(1, _T("バージョン"), LVCFMT_LEFT,
            rcList.Width() - 180 - nScrollWidth - n3DEdge * 2, -1);

        DWORD dwMajor, dwMinor;
        CString strInfo;

        AtlGetShellVersion(&dwMajor, &dwMinor);
        strInfo.Format(_T("%d.%02d"), dwMajor, dwMinor);
        m_list_info.AddItem(0, 0, _T("shell32.dll"));
        m_list_info.AddItem(0, 1, strInfo);

        AtlGetCommCtrlVersion(&dwMajor, &dwMinor);
        strInfo.Format(_T("%d.%02d"), dwMajor, dwMinor);
        m_list_info.AddItem(1, 0, _T("comctl32.dll"));
        m_list_info.AddItem(1, 1, strInfo);

        return TRUE;
    }

    void SwitchWindow(bool bShow){
        int nIndex = m_tab_display.GetCurSel();
        TCITEM ti;
        ti.mask = TCIF_PARAM;
        m_tab_display.GetItem(nIndex, &ti);
        CWindow win = (HWND)ti.lParam;
        win.ShowWindow(bShow ? SW_SHOW : SW_HIDE);
        if(bShow)
            win.SetFocus();
    }

    LRESULT OnTabSelChanging(LPNMHDR pnmh){
        SwitchWindow(false);
        return FALSE;
    }

    LRESULT OnTabSelChange(LPNMHDR pnmh){
        SwitchWindow(true);
        return 0;
    }

    void OnOK(UINT uNotifyCode, int nID, CWindow wndCtl){
        EndDialog(nID);
    }

    void OnCancel(UINT uNotifyCode, int nID, CWindow wndCtl){
        EndDialog(nID);
    }
};
			

// SampleProject.cpp
#include "stdafx.h"
#include "resource.h"
#include "MainDlg.h"

CAppModule _Module;

int WINAPI _tWinMain(HINSTANCE hInstance, 
    HINSTANCE /*hPrevInstance*/, LPTSTR /*lpstrCmdLine*/, int /*nCmdShow*/)
{
    HRESULT hRes = ::CoInitialize(NULL);
    ATLASSERT(SUCCEEDED(hRes));

    ::DefWindowProc(NULL, 0, 0, 0L);

    AtlInitCommonControls(ICC_WIN95_CLASSES);

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

    CMainDlg dlg;
    int nRet = (int) dlg.DoModal();

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

    return nRet;
}
			

 まず、リソースを作成します。ダイアログにタブコントロールとリストビューコントロールを配置し、 それぞれの[ID]を次のように設定します。 なお、2つのリストビューコントロールの[プロパティ]では、[View]を[レポート]に設定し、 [Always Show Selection]を[True]に設定します。 また、DLLのバージョン情報表示用リストビューコントロールだけ[Visible]を[False]に設定します。

コントロール名 ID 備考
タブ IDC_TAB_DISPLAY
リストビュー IDC_LIST_FILE ファイル一覧表示用
リストビュー IDC_LIST_INFO DLLのバージョン情報表示用

 次に、stdafx.hヘッダでは、CTabCtrlクラスとCListViewCtrlクラスを使用するためにatlctrls.hヘッダをインクルードします。

 CMainDlgクラスでは、 タブコントロールとリストビューコントロール用にそれぞれCTabCtrlクラスと CListViewCtrlクラスのインスタンスをメンバ変数として宣言します。 これを使うためには、WM_INITDIALOGメッセージハンドラでコントロールのハンドルを代入する必要があります。

 次に、WM_INITDIALOGメッセージハンドラで各コントロールを配置します。 まず、タブコントロールをダイアログより余白(nPaddingXnPaddingY)の分だけ小さく配置します。 そしてタブに2つのアイテム([ファイル]と[DLL情報])を挿入します。 この時、2つのリストビューコントロールのハンドルをそれぞれTCITEM構造体のlParamに設定します。 次に、タブコントロールの表示領域(タブコントロールのタブ部分を除いた矩形)を取得し、 その領域に合うように2つのリストビューコントロールを配置します。 ファイル一覧表示用リストビューコントロールにはカレントディレクトリのファイル一覧を追加し、 DLLのバージョン表示用リストビューコントロールにはshell32.dllとcomctl32.dllのバージョン情報を追加します。

 次に、通知コードがTCN_SELCHANGINGのタブコントロール用WM_NOTIFYメッセージハンドラとしてOnTabSelChanging()を追加します。 このハンドラ関数はタブが切り替わる直前に呼び出されますが、 ここではGetCurSel()によって切り替わる直前のタブのインデックスを取得し、 そのインデックスのタブアイテムからリストビューコントロールのウィンドウハンドルを取得して、 そのリストビューコントロールを不可視にします。

 次に、通知コードがTCN_SELCHANGEのタブコントロール用WM_NOTIFYメッセージハンドラとしてOnTabSelChange()を追加します。 このハンドラ関数はタブが切り替わった直後に呼び出されますが、 ここではGetCurSel()によって切り替わった直後のタブのインデックスを取得し、 そのインデックスのタブアイテムからリストビューコントロールのウィンドウハンドルを取得して、 そのリストビューコントロールを可視にします。

 最後に_tWinMain()で、引数にICC_WIN95_CLASSESを指定してAtlInitCommonControls()を呼び出します。