Top > プログラミング関連 > 「閉じる」ボタン付きタブビュー
2007/3/7 記述
タブビューやタブコントロールはプロパティシートなどでも使用される一般的なコントロールです。タブビューは便利なのですが、タブブラウザを見るとタブに「閉じる」ボタンが付いている場合があります。これはなかなか便利なものです。
そこで、「閉じる」ボタン付きタブビューを実装します。例によって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を適用します。