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

VC++ 多文檔架構 (MDI) 中整合可停靠樹狀控制列

     編輯:關於VC++

本文示範在 MDI 應用程式中,利用 Cristi Posea 的 CSizingControlBar 實作可調整大小、可停靠的控制列,並在其中嵌入 CTreeCtrl 導覽樹,點擊樹節點即可在右側視圖顯示對應內容。這是商業軟體常見的「導覽窗格 + 內容區」經典佈局。

執行結果:左側可停靠樹狀控制列,右側視圖顯示節點標題。

架構概覽

  1. 專案包含 SizingControlBar.h/.cpp (第三方開源庫,支援動態調整大小)。
  2. 衍生 CMyBar : public CSizingControlBar 作為控制列視窗。
  3. 衍生 CMyTree : public CTreeCtrl 處理樹節點點擊事件。
  4. 主框架 CMainFrame 建立並停靠 CMyBar。
  5. 視圖類別 CMyView 提供 DrawRect 繪製節點標題。
  6. 應用程式類別持有視圖指標,供樹控件跨模組呼叫。

關鍵實作步驟

1. 加入 SizingControlBar

將 SizingControlBar.h/.cpp 複製至專案目錄並加入專案。此類別繼承自 CControlBar,支援 CBRS_SIZE_DYNAMIC 風格。

2. 建立控制列類別 CMyBar

用 ClassWizard 衍生自 CToolBar,再手動將基類改為 CSizingControlBar。

// MyBar.h class CMyBar : public CSizingControlBar { DECLARE_DYNCREATE(CMyBar) public: CMyTree m_TreeCtrl; // 內嵌樹控件 // ... virtual void OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnSize(UINT nType, int cx, int cy); DECLARE_MESSAGE_MAP() }; // MyBar.cpp void CMyBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler) { UpdateDialogControls(pTarget, bDisableIfNoHndler); // 支援按鈕啟用/禁用 } int CMyBar::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CSizingControlBar::OnCreate(lpCreateStruct) == -1) return -1; // 建立樹控件 m_TreeCtrl.Create(WS_VISIBLE | WS_CHILD | WS_BORDER | WS_TABSTOP | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT | TVS_DISABLEDRAGDROP | TVS_EDITLABELS | TVS_TRACKSELECT, CRect(10,10,300,100), this, ID_TREECTRL); // 設定預設 GUI 字型 CFont* pFont = CFont::FromHandle((HFONT)GetStockObject(DEFAULT_GUI_FONT)); m_TreeCtrl.SetFont(pFont); // 建立範例樹節點 HTREEITEM hRoot = m_TreeCtrl.InsertItem(_T("VCKBASE"), 0, 0); HTREEITEM h1 = m_TreeCtrl.InsertItem(_T("程式設計師社群"), 1, 1, hRoot); HTREEITEM h2 = m_TreeCtrl.InsertItem(_T("文檔中心"), 1, 1, hRoot); // ... 續加子節點 ... m_TreeCtrl.InsertItem(_T("開發論壇"), 1, 1, h1); m_TreeCtrl.InsertItem(_T("開發聯盟"), 1, 1, h1); // ... m_TreeCtrl.SelectItem(hRoot); m_TreeCtrl.Expand(hRoot, TVE_EXPAND); return 0; } void CMyBar::OnSize(UINT nType, int cx, int cy) { CSizingControlBar::OnSize(nType, cx, cy); if (m_TreeCtrl.m_hWnd) { CRect rc; GetClientRect(&rc); m_TreeCtrl.MoveWindow(&rc); // 佔滿控制列客戶區 } }

3. 主框架建立並停靠控制列

// MainFrm.h class CMainFrame : public CMDIFrameWnd { CMyBar m_CtrlBar; // 成員變數 // ... }; // MainFrm.cpp int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_CtrlBar.Create(_T("資料瀏覽列"), this, CSize(200,200), TRUE, 123)) { TRACE0("Failed to create CMyBar\n"); return -1; } m_CtrlBar.SetBarStyle(m_CtrlBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); m_CtrlBar.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_CtrlBar, AFX_IDW_DOCKBAR_LEFT); // 預設停靠左側 return 0; }

4. 樹控件處理左鍵點擊 — 通知視圖更新

// MyTree.h class CMyTree : public CTreeCtrl { UINT m_uFlags; afx_msg void OnLButtonDown(UINT nFlags, CPoint point); DECLARE_MESSAGE_MAP() }; // MyTree.cpp void CMyTree::OnLButtonDown(UINT nFlags, CPoint point) { HTREEITEM hItem = HitTest(point, &m_uFlags); if (m_uFlags & TVHT_ONITEMLABEL) // 點擊標籤文字區域 { CMyApp* pApp = (CMyApp*)AfxGetApp(); if (pApp->pView) // 應用程式類別持有視圖指標 { pApp->pView->m_Title = GetItemText(hItem); pApp->pView->Invalidate(TRUE); // 觸發重繪 } SelectItem(hItem); } CTreeCtrl::OnLButtonDown(nFlags, point); }

5. 視圖類別繪製標題

// MyView.h class CMyView : public CView { public: CString m_Title; void DrawRect(CDC* pDC); }; // MyView.cpp void CMyView::DrawRect(CDC* pDC) { CRect rect(100, 100, 400, 400); pDC->Rectangle(&rect); CRect textRect(100, 100, 250, 250); pDC->DrawText(m_Title, &textRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); } void CMyView::OnDraw(CDC* pDC) { DrawRect(pDC); } void CMyView::OnInitialUpdate() { CView::OnInitialUpdate(); CMyApp* pApp = (CMyApp*)AfxGetApp(); pApp->pView = this; // 註冊自身指標 }

6. 應用程式類別持有視圖指標

// MyApp.h class CMyApp : public CWinApp { public: CMyView* pView = nullptr; // 指向目前作用中視圖 // ... };

MDI 特殊處理

MDI 下主框架繼承 CMDIFrameWnd,視圖為 CMDIChildWnd 管理。上述架構同樣適用,只需確保 pView 指向目前啟用的子視圖 (可在 CMDIFrameWnd::MDIActivate 或視圖 OnActivateView 更新)。

常見問題與解決

  • 控制列無法調整大小:確認 CSizingControlBar 正確加入專案,且 CBRS_SIZE_DYNAMIC 風格已設定。
  • 樹控件不顯示:檢查 OnCreate 中 Create 參數,確保 WS_VISIBLE | WS_CHILD 且矩形非空。
  • 點擊節點視圖不更新:檢查 AfxGetApp() 轉型是否正確,pView 是否已在 OnInitialUpdate 指派。

本範例展示 MFC 文檔/視圖架構下,如何靈活組合第三方控制列庫與標準控件,建構專業級導覽介面。完整專案碼可從 VC 知識庫下載。

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