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

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

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

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



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

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

// maindlg.h内
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_EX(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()

    LRESULT OnInitDialog(HWND hWnd, LPARAM lParam){
        // スクリーンの中央に配置
        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);

        // タブアイテム挿入
        TCITEM ti;
        ti.mask = TCIF_TEXT | TCIF_PARAM;

        ti.pszText = _T("ファイル");
        ti.lParam = (LPARAM)m_list_file.m_hWnd;
        m_tab_display.InsertItem(0, &ti);

        ti.pszText = _T("DLL情報");
        ti.lParam = (LPARAM)m_list_info.m_hWnd;
        m_tab_display.InsertItem(1, &ti);

        // タブコントロールの表示領域取得
        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, 220, -1);
        m_list_info.InsertColumn(1, _T("バージョン"), LVCFMT_LEFT,
            rcList.Width() - 220 - 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, HWND hWndCtl){
        EndDialog(nID);
    }

    void OnCancel(UINT uNotifyCode, int nID, HWND hWndCtl){
        EndDialog(nID);
    }
};
			

// Control.cpp内
#include "stdafx.h"

#include "resource.h"

#include "maindlg.h"

CAppModule _Module;

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

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

    AtlInitCommonControls(ICC_COOL_CLASSES | ICC_WIN95_CLASSES);

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

    int nRet = 0;
    // BLOCK: アプリケーション実行
    {
        CMainDlg dlgMain;
        nRet = dlgMain.DoModal();
    }

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

    return nRet;
}
			

 まず、リソースを作成します。ダイアログにタブコントロールとリストビューコントロールを配置し、 リソースIDを次のように指定します。 なお、2つのリストビューコントロールの[スタイル]ではデフォルトに加え[表示]で[レポート]を選択し、 [選択を常に表示]にチェックを入れます。 さらに、[DLL情報]用リストビューコントロールだけ[一般]の[可視]のチェックをはずします。

コントロール名 リソースID
タブ IDC_TAB_DISPLAY
リストビュー([ファイル]用) IDC_LIST_FILE
リストビュー([DLL情報]用) IDC_LIST_INFO

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

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

 次に、WM_INITDIALOGメッセージハンドラで各コントロールを配置します。 まず、タブコントロールをダイアログよりnPaddingXnPaddingYの分(余白)だけ小さく配置します。 そしてタブに2つのアイテム([ファイル]と[DLL情報])を挿入します。 この時、2つのリストビューコントロールのハンドルをそれぞれTCITEM構造体のlParamに設定します。

その後、タブコントロールの表示領域(タブコントロールのタブ部分を除いた矩形)を取得し、 その領域に合うように2つのリストビューコントロールを配置します。

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

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