Top > プログラミング関連 > 「閉じる」ボタン付きタブビュー

「閉じる」ボタン付きタブビュー

2007/3/7 記述

[「閉じる」ボタン付きタブビュー]

ダウンロード(39.2KB)

概要

タブビューやタブコントロールはプロパティシートなどでも使用される一般的なコントロールです。タブビューは便利なのですが、タブブラウザを見るとタブに「閉じる」ボタンが付いている場合があります。これはなかなか便利なものです。

そこで、「閉じる」ボタン付きタブビューを実装します。例によってWTLを使います。今回はSTLのvectorも使用します(使わないようにすることも可能です)。

The So-Software Studioのタブビューの解説をベースに作成しました。


原理

Spy++で調べる限り、タブコントロールの「つまみ」の部分は独立したウィンドウではないようです。そこで、GetItemRect()でつまみの領域を取得し、SetItemSize()SetMinTabWidth()でボタンの場所を確保してからボタンをタブビューの子ウィンドウとして作成します。

ここで、このボタンはCBitmapButtonの派生にしてあります。これにより、自然な「閉じる」ボタンができあがります。

// TClient=CEdit,TButton=CBitmapButtonの派生クラス
void AddTab(){
    // カレントタブ内のクライアントウィンドウを非表示にする
    ShowCurrentClient(false);

    // タブ名を作成
    CString strTitle;
    strTitle.Format(_T("タブ%d"), GetItemCount());

    // タブに表示するクライアントウィンドウを作成
    TClient* lpClient = new TClient;
    lpClient->Create(m_hWnd, rcDefault, NULL,
        WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | 
        ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_MULTILINE | ES_NOHIDESEL | ES_SAVESEL, 
        WS_EX_CLIENTEDGE);
    //ウィンドウスタイルは、適宜変更してください。

    // タブを挿入
    TCITEM ti;
    ti.mask = TCIF_TEXT;
    ti.pszText = (LPTSTR)(LPCTSTR)strTitle;
    int nIndex = InsertItem(GetItemCount(), &ti);

    if(m_bFirstItem){
        CRect rect;
        // タブの領域を取得
        GetItemRect(nIndex,rect);
        //タブのサイズを大きめにしておく
        CSize size(135,rect.Height());
        SetItemSize(size);
        SetMinTabWidth(size.cx);
        m_bFirstItem=false;
    }
    // タブの領域を取得
    CRect rect;
    GetItemRect(nIndex,rect);

    //ボタンの配置
    rect.right-=::GetSystemMetrics(SM_CXFIXEDFRAME);
    rect.left=rect.right-rect.Height();    //正方形に合わせる
    TButton *lpButton=new TButton;
    lpButton->Create(m_hWnd,rect,_T("X"),WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON|BS_CENTER|BS_VCENTER,0,ID_TABBUTTON_CLOSE_ITEM);

    //アイテムデータ追加
    m_ItemArray.push_back(std::pair<TClient*,TButton*>(lpClient,lpButton));

    // 挿入したタブをカレントにしてクライアントウィンドウにフォーカスを与える
    SetCurSel(nIndex);
    lpClient->SetFocus();

    // クライアントウィンドウをリサイズ
    ResizeClient(nIndex);

    AdjustButtons();
}

あとは、ボタンのイベントハンドラなどでどのボタンを閉じるか、などを実装すればOKです。

今回STLのvectorを使ったのは、タブと「閉じる」ボタンの対応を記録するためですが、タブ挿入時に以下の例のようにしていくつか書き換えれば、vector無しでも実装は可能です。

struct PTRPAIR{
    CEdit *lpEdit;
    CButton *lpButton;
};
//----
PTRPAIR *lpPtrPair=new PTRPAIR;
lpPtrPair->lpEdit=new CEdit;
lpPtrPair->lpButton=new CButton;

TCITEM ti;
ti.mask = TCIF_TEXT | TCIF_PARAM;
ti.pszText = "Title";
ti.lParam = (LPARAM)lpPtrPair;
int nIndex = InsertItem(GetItemCount(), &ti);

コードについて

このコードにはNYSL 0.9982を適用します。

戻る


[Claybird Logo]泥巣 by Claybird <claybird.without.wing@gmail.com>