採用 VC + SQL Server 架構的 MFC 單文檔應用程式,核心需求包含:視窗分割、多視圖通訊、列表控件操作、樹狀控件遞歸建立目錄、主從表資料顯示。本文針對各關鍵技術點進行模組化說明。
CSplitterWnd於 CMainFrame::OnCreateClient() 中建立兩層巢狀分割:
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) {
CRect rect; GetClientRect(&rect);
// 第一層:1列2欄 (左:樹狀目錄, 右:再分割)
m_wndSplitter1.CreateStatic(this, 1, 2);
m_wndSplitter1.CreateView(0, 0, RUNTIME_CLASS(CClassTreeView), CSize(150,150), pContext);
// 第二層:針對右側窗格 (0,1) 再切 2列1欄 (上:主表, 下:從表)
m_wndSplitter2.CreateStatic(&m_wndSplitter1, 2, 1, WS_CHILD|WS_VISIBLE,
m_wndSplitter1.IdFromRowCol(0,1));
m_wndSplitter2.CreateView(0, 0, RUNTIME_CLASS(CDagView), CSize(0,0), pContext); // 主表
m_wndSplitter2.CreateView(1, 0, RUNTIME_CLASS(CDagDetailView), CSize(0,0), pContext); // 從表
m_wndSplitter2.SetRowInfo(0, rect.Height()/2, 0); // 初始上下各半
return TRUE; // 切記不可呼叫基類 OnCreateClient
}
關鍵點:CreateStatic 建立固定行列,CreateView 填入不同 CView 衍生類,IdFromRowCol 取得窗格 ID 供巢狀分割使用。
因專案僅單一 CDocument,額外視圖不共享文件,故採「主框架中轉」法:
CMainFrame* pFrame = static_cast<CMainFrame*>(AfxGetMainWnd());
CDagDetailView* pDetail = static_cast<CDagDetailView*>(
pFrame->m_wndSplitter2.GetPane(1, 0)); // 取得下方面板指標
// 現在可呼叫 pDetail->RefreshData() 等自訂函式
建議使用 static_cast 而非 C 風格轉型,型別安全且易維護。
CListCtrl 進階操作SetWindowLong(m_hWnd, GWL_STYLE, LVS_REPORT | ...) 設定 LVS_REPORT 風格,呈現類 DataGrid 效果。ListView_SetExtendedListViewStyleEx(m_hWnd, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES, ...) 啟用整列選取、格線。NM_CLICK:單擊回應(需自行 HitTest 判斷欄位)。LVN_ITEMCHANGED:選取變更,NM_LISTVIEW* pNM = (NM_LISTVIEW*)pNMHDR 判斷 uChanged & LVIF_STATE 及 uNewState & LVIS_SELECTED。CTreeCtrl 遞歸建立資料庫目錄遞歸函式 BuildTree(HTREEITEM hParent, long lParentID):
SELECT * FROM Categories WHERE ParentID = ?。InsertItem 取得 HTREEITEM hChild,SetItemData(hChild, lChildID) 存放主鍵。BuildTree(hChild, lChildID) 處理子節點。配合 TVN_SELCHANGED 事件,取得 GetItemData(hSel) 即為該節點 ID,進而查詢從表資料刷新列表。
採用 CRecordset (或 ADO) 兩組資料集:
m_rsMaster 綁定主表列表,m_rsDetail 依主表選取的 PK 篩選 (m_strFilter = "MasterID = " + strID) 並 Requery()。列表 LVN_ITEMCHANGED 事件中更新從表過濾條件並重查。
靜態分割奠定版面基礎,主框架中轉解決視圖通訊,列表/樹狀控件配合資料庫操作完成主從表互動。模組化設計讓各功能低耦合、高內聚,易於擴展維護。