首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

MFC CTabCtrl 分頁控件完整指南

     編輯:關於C語言

分頁控件核心概念

CTabCtrl 提供「分頁介面」,每個分頁對應一組子控件。切換分頁時,**開發者需自行顯示/隱藏對應子控件**,控件本身不管理子視窗生命週期。

建立與基本設定


// 建立
m_tab.Create(WS_CHILD | WS_VISIBLE | TCS_SINGLELINE, 
             CRect(10,10,300,200), this, IDC_TAB_MAIN);

// 分頁樣式
// TCS_TABS         標準分頁(預設)
// TCS_BUTTONS      按鈕外觀分頁
// TCS_MULTILINE    多行分頁
// TCS_SINGLELINE   單行分頁(預設)
// TCS_RIGHTJUSTIFY 右對齊
// TCS_FIXEDWIDTH   固定寬度分頁
// TCS_OWNERDRAWFIXED 自訂繪製固定高度

新增分頁:文字與圖示


// 純文字
m_tab.InsertItem(0, _T("基本設定"));
m_tab.InsertItem(1, _T("進階選項"));
m_tab.InsertItem(2, _T("關於"));

// 帶圖示(需先設定 ImageList)
CImageList imgList;
imgList.Create(IDB_TAB_ICONS, 16, 1, RGB(255,0,255));  // 16x16, 透明色
m_tab.SetImageList(&imgList);

m_tab.InsertItem(0, _T("基本"), 0);  // 圖示索引 0
m_tab.InsertItem(1, _T("進階"), 1);
m_tab.InsertItem(2, _T("關於"), 2);

分頁切換處理:核心邏輯


// 訊息映射
ON_NOTIFY(TCN_SELCHANGE, IDC_TAB_MAIN, OnTabSelChange)
ON_NOTIFY(TCN_SELCHANGING, IDC_TAB_MAIN, OnTabSelChanging)

// 目前選中分頁索引
int nCur = m_tab.GetCurSel();
m_tab.SetCurSel(1);  // 程式切換至第 2 頁

// 刪除分頁
m_tab.DeleteItem(0);
m_tab.DeleteAllItems();

切換時顯示/隱藏子控件(標準模式)


// 成員變量:每個分頁對應一個子對話框或控件群組
CEdit   m_editPage1;
CListCtrl m_listPage2;
CButton m_btnPage3;

void CParentWnd::OnTabSelChange(NMHDR* pNMHDR, LRESULT* pResult)
{
    int nPage = m_tab.GetCurSel();
    
    // 隱藏所有
    m_editPage1.ShowWindow(SW_HIDE);
    m_listPage2.ShowWindow(SW_HIDE);
    m_btnPage3.ShowWindow(SW_HIDE);

    // 顯示對應頁面
    switch (nPage)
    {
    case 0: m_editPage1.ShowWindow(SW_SHOW); break;
    case 1: m_listPage2.ShowWindow(SW_SHOW); break;
    case 2: m_btnPage3.ShowWindow(SW_SHOW); break;
    }
    *pResult = 0;
}

// 切換前可攔截(如未儲存資料詢問)
void CParentWnd::OnTabSelChanging(NMHDR* pNMHDR, LRESULT* pResult)
{
    if (m_bDataDirty && AfxMessageBox(_T("資料未儲存,確定切換?"), MB_YESNO) != IDYES)
    {
        *pResult = TRUE;  // 取消切換
        return;
    }
    *pResult = FALSE;  // 允許切換
}

進階:每個分頁獨立對話框(子對話框模式)

將每個分頁內容封裝為 CDialog 派生類(Style=Child, Border=None),作為 Tab Control 的子視窗:


// 頁面對話框類別
class CPage1Dlg : public CDialog
{
    DECLARE_DYNCREATE(CPage1Dlg)
public:
    CPage1Dlg() : CDialog(IDD_PAGE1) {}
    // DDX/DDV、訊息映射...
};

// 父視窗建立頁面
void CParentWnd::CreatePages()
{
    m_page1.Create(IDD_PAGE1, &m_tab);
    m_page2.Create(IDD_PAGE2, &m_tab);
    m_page3.Create(IDD_PAGE3, &m_tab);

    // 定位於 Tab Control 客戶區
    CRect rc;
    m_tab.GetClientRect(&rc);
    m_tab.AdjustRect(FALSE, &rc);  // 取得分頁內容區域
    m_page1.MoveWindow(&rc);
    m_page2.MoveWindow(&rc);
    m_page3.MoveWindow(&rc);

    m_page1.ShowWindow(SW_SHOW);
    m_page2.ShowWindow(SW_HIDE);
    m_page3.ShowWindow(SW_HIDE);
}

void CParentWnd::OnTabSelChange(NMHDR*, LRESULT* pResult)
{
    int n = m_tab.GetCurSel();
    m_page1.ShowWindow(n==0 ? SW_SHOW : SW_HIDE);
    m_page2.ShowWindow(n==1 ? SW_SHOW : SW_HIDE);
    m_page3.ShowWindow(n==2 ? SW_SHOW : SW_HIDE);
    *pResult = 0;
}

常用屬性與方法速查

函式用途
GetCurSel()取得目前分頁索引(-1 表無選中)
SetCurSel(n)設定目前分頁
GetItemCount()分頁總數
GetItem(n, TCITEM*)取得分頁屬性(文字、圖示、資料指標)
SetItem(n, TCITEM*)修改分頁屬性
GetItemRect(n, LPRECT)取得分頁標籤矩形
AdjustRect(BOOL bLarger, LPRECT)計算內容區域(bLarger=FALSE 縮小)
SetImageList(CImageList*)設定圖示清單
RemoveImage(n)移除指定圖示

自訂繪製

  1. 建立時加 TCS_OWNERDRAWFIXED 樣式。
  2. 父視窗處理 WM_DRAWITEM(ON_WM_DRAWITEM())。
  3. 繪製代碼:

void CParentWnd::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDIS)
{
    if (nIDCtl == IDC_TAB_MAIN && lpDIS->CtlType == ODT_TAB)
    {
        CDC dc; dc.Attach(lpDIS->hDC);
        CRect rc = lpDIS->rcItem;
        int nIndex = lpDIS->itemID;
        BOOL bSelected = lpDIS->itemState & ODS_SELECTED;

        // 背景
        dc.FillSolidRect(rc, bSelected ? RGB(255,255,255) : RGB(230,230,230));
        // 邊框
        dc.DrawEdge(rc, bSelected ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT);
        // 文字
        CString str = m_tab.GetItemText(nIndex);
        dc.SetBkMode(TRANSPARENT);
        dc.DrawText(str, rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
        dc.Detach();
        return;
    }
    CWnd::OnDrawItem(nIDCtl, lpDIS);
}

常見問題

  • 分頁切換閃爍:使用 WS_CLIPCHILDREN | WS_CLIPSIBLINGS 父視窗樣式,或雙緩衝繪製。
  • 子控件 Tab 鍵無法巡覽:父視窗 PreTranslateMessage 需正確轉發,或確保子對話框 Style=Child。
  • 圖示不顯示:ImageList 色深與螢幕不符、圖示尺寸不匹配(通常 16x16)、透明色設定錯誤。
  • 動態新增/刪除分頁後索引錯亂:儲存分頁關聯資料用 TCITEM::lParam 指標,而非依賴索引。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved