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

VC++ 列表控件驅動屬性表 (CMyPropertySheet)

     編輯:關於VC++

前言

MFC CPropertySheet 預設使用 CTabCtrl 切換頁面,介面傳統且難以客製化。現代應用常採用左側 列表控件 (CListCtrl) 作為導覽,右側顯示對應屬性頁。本文實作 CMyPropertySheet 繼承 CPropertySheet,替換 Tab 為 List,支援圖示、自訂顏色/字型、完整保留原生屬性頁功能。

效果預覽

使用方法

// 1. 建立兩個 CPropertyPage 衍生頁面
CPageGeneral m_page1;
CPageAdvanced m_page2;

// 2. 建立屬性表並加入頁面
CMyPropertySheet myPS;
myPS.AddPage(&m_page1);
myPS.AddPage(&m_page2);

// 3. 設定列表項圖示 (順序與 AddPage 一致)
myPS.AddIcon(IDI_GLOBAL);    // 第 0 頁圖示
myPS.AddIcon(IDI_ADDITION);  // 第 1 頁圖示

// 4. 可選外觀調整
myPS.SetSeparatorColor(RGB(180,180,180)); // 分隔線色
myPS.SetCaptionColor(RGB(0,0,128));       // 標題列色
myPS.SetSelectedColor(RGB(200,220,255));  // 選取項背景色
myPS.SetListFont(_T("微軟正黑體"), 10);   // 列表字型

// 5. 模態顯示
myPS.DoModal();

核心實現邏輯

OnInitDialog:佈局重構

BOOL CMyPropertySheet::OnInitDialog()
{
    BOOL bResult = CPropertySheet::OnInitDialog();

    // 1. 取得原始頁面矩形
    CRect rectPage, rect, rectTab;
    GetPage(0)->GetWindowRect(&rectPage);
    GetWindowRect(&rect);

    // 2. 擴寬視窗 150px 容納列表,頁面右移
    rect.right += 150;
    int nPageWidth = rectPage.Width();
    rectPage.right = rect.right - 20;
    rectPage.left = rectPage.right - nPageWidth;
    ScreenToClient(&rectPage);
    m_rectPage = rectPage; // 保存供切換時用

    MoveWindow(&rect);           // 調整外框
    GetPage(0)->MoveWindow(&rectPage); // 移動第一頁

    // 3. 隱藏原始 TabCtrl
    CTabCtrl* pTab = GetTabControl();
    pTab->GetWindowRect(&rectTab);
    ScreenToClient(&rectTab);
    pTab->ShowWindow(SW_HIDE);

    // 4. 建立列表控件
    m_wndList.Create(WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_NOCOLUMNHEADER,
                     CRect(10, rectTab.top, 150, rectPage.bottom), this, 0xFFFF);
    m_wndList.SetExtendedStyle(LVS_EX_FULLROWSELECT);
    m_wndList.SetImageList(&m_imgList, LVSIL_SMALL);

    // 5. 初始化列表項 (從頁面標題+圖示)
    InitList();

    // 6. 設定列表行高 (字型大小決定)
    CFont font;
    font.CreatePointFont(240, _T("宋體")); // 12pt
    m_wndList.SetFont(&font);

    // 7. 同步第一頁標題
    CString strCaption;
    GetPage(0)->GetWindowText(strCaption);
    _tcscpy(m_szCaption, strCaption);

    return bResult;
}

列表點擊切換頁面

void CMyPropertySheet::OnNMClick(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMITEMACTIVATE lpItem = reinterpret_cast(pNMHDR);
    if (lpItem->iItem >= 0 && lpItem->iItem < m_wndList.GetItemCount())
    {
        m_nSelectedItem = lpItem->iItem;
        CString strCaption = m_wndList.GetItemText(lpItem->iItem, 0);
        _tcscpy(m_szCaption, strCaption);

        SetActivePage(m_nSelectedItem); // MFC 內建切換邏輯

        Invalidate(); // 重繪標題列
        GetPage(m_nSelectedItem)->MoveWindow(&m_rectPage); // 確保位置
        m_wndList.SetFocus();
    }
    *pResult = 0;
}

自繪列表 (OnNMCustomDraw)

處理 NM_CUSTOMDRAW 繪製:

  • 選取項:填充 m_clrSelected、繪製焦點虛線框
  • 分隔線:每項底部畫 m_clrSeparator
  • 圖示+文字:DrawIconEx + TextOut,文字色 m_clrCaption

擴充建議

  • 改用 TreeCtrl 支援多層分類導覽。
  • 加入 圖示拖曳排序 對應頁面順序調整。
  • 支援 動態增減頁面 (運行時 AddPage/RemovePage 同步更新列表)。
  • 整合 Office 2007 Ribbon 風格:列表改為垂直按鈕群組。

編譯環境

Visual C++ 2005 (VC8) / MFC 8.0,VC6.0 需微調 reinterpret_cast 與 LVS_EX_FULLROWSELECT 相容性。

完整原始碼 MyPropertySheet.h/cpp 可直接加入專案使用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved