在 MFC 開發中,CTreeCtrl 樹形控件是構建類似資源管理器介面的常用組件。本文將詳細介紹如何利用 CTreeCtrl 搭配 Child Dialog 實現主對話框內多視圖動態切換的技術,避免彈出式視窗造成的介面雜亂。
首先建立一個基於對話框的 MFC 專案(命名為 MFC_TreeCtrl)。在資源視圖中新增兩個 Dialog 資源,ID 分別設為 IDD_DIALOG11 和 IDD_DIALOG211,將 Style 設為 Child、Border 設為 None。分別為它們建立類別 Cdialog11 和 Cdialog211,並在主對話框類別的 CPP 檔中包含對應的標頭檔。
匯入數個圖示資源作為樹形節點圖示。在主對話框放置一個 CTreeCtrl 控件(ID 保持預設),透過類別向導新增變數 m_mytree。
CDialog* m_treePages[2];
CString node_name;
BOOL InitMytree();
m_treePages[0] = new Cdialog11;
m_treePages[1] = new Cdialog211;
BOOL CMFC_TreeCRTLDlg::InitMytree()
{
// 載入節點圖示
HICON icon[2];
icon[0] = AfxGetApp()->LoadIcon(IDI_ICON6);
icon[1] = AfxGetApp()->LoadIcon(IDI_ICON7);
// 建立影像清單
CImageList* m_imagelist = new CImageList;
m_imagelist->Create(16, 16, ILC_COLOR32, 2, 2);
m_imagelist->SetBkColor(RGB(255, 255, 255));
for (int n = 0; n < 2; n++)
m_imagelist->Add(icon[n]);
m_mytree.SetImageList(m_imagelist, TVSIL_NORMAL);
m_mytree.SetBkColor(RGB(0, 250, 255));
// 建立樹形節點結構
HTREEITEM root0 = m_mytree.InsertItem(_T("Dialog1"), 0, 1, TVI_ROOT, TVI_LAST);
HTREEITEM root1 = m_mytree.InsertItem(_T("Dialog2"), 0, 1, TVI_ROOT, TVI_LAST);
HTREEITEM sub_son0 = m_mytree.InsertItem(_T("Dialog 1-1"), 0, 1, root0, TVI_LAST);
HTREEITEM sub_son1 = m_mytree.InsertItem(_T("Dialog 2-1"), 0, 1, root1, TVI_LAST);
HTREEITEM sub_m_son0 = m_mytree.InsertItem(_T("Dialog 2-1-1"), 0, 1, sub_son1, TVI_LAST);
// 建立並定位子對話框
m_treePages[0]->Create(IDD_DIALOG11, this);
m_treePages[1]->Create(IDD_DIALOG211, this);
m_treePages[0]->ShowWindow(SW_SHOW);
m_treePages[1]->ShowWindow(SW_HIDE);
CRect m_rect;
GetClientRect(&m_rect);
m_rect.left = 200;
m_treePages[0]->MoveWindow(&m_rect);
m_treePages[1]->MoveWindow(&m_rect);
return TRUE;
}
透過類別向導為 IDC_TREE1 新增 TVN_SELCHANGED 訊息處理函數:
void CMFC_TreeCRTLDlg::OnSelchangedTree1(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
UpdateData(TRUE);
node_name = m_mytree.GetItemText(pNMTreeView->itemNew.hItem);
SetWindowText(node_name); // 標題列顯示節點名稱
// 視節點切換顯示對應對話框
if (node_name == _T("Dialog 1-1")) {
m_treePages[0]->ShowWindow(SW_SHOW);
m_treePages[1]->ShowWindow(SW_HIDE);
}
else if (node_name == _T("Dialog 2-1-1")) {
m_treePages[0]->ShowWindow(SW_HIDE);
m_treePages[1]->ShowWindow(SW_SHOW);
}
UpdateData(FALSE);
*pResult = 0;
}
在 OnInitDialog() 中呼叫 InitMytree() 完成初始化。
程式執行後,左側樹形控件顯示階層節點,點選不同節點時,右側區域動態切換對應的 Child Dialog。這種設計讓單一主視窗即可承載多個功能模組,介面清爽且易於維護,適用於工具箱、設定面板、多功能整合介面等場景。

圖一:程式執行效果圖