CSplitterWnd 佔據框架視窗客戶區,視圖佔據分割窗格。兩種模式各有適用場景:
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);
// 第二層:右側再上下分割(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 參數為 (parent, rows, cols);巢狀分割器的 parent 為上層分割器,且需透過 IdFromRowCol 取得窗格 ID。
本專案單一 Document,多視圖類獨立,採「主框架→分割器→窗格」路徑取得視圖指標:
CMainFrame* pFrame = static_cast(AfxGetMainWnd());
CDagDetailView* pDetailView = static_cast(
pFrame->m_wndSplitter2.GetPane(1, 0)); // 第 1 列第 0 行
// 取得指標後即可呼叫視圖公用方法、存取資料成員
最佳實踐: 使用 static_cast 而非 C 風格強轉,編譯期即可檢查型別安全。
LVS_REPORT 呈現類 DataGrid 列表,需搭配 SetWindowLong(GWL_STYLE, ...) 設定擴充風格(LVS_EX_FULLROWSELECT、LVS_EX_GRIDLINES 等)。NM_CLICK:單擊項目LVN_ITEMCHANGED:選取狀態變更(含鍵盤導航)NM_DBLCLK:雙擊編輯/鑽取void CDagView::OnItemChanged(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if ((pNMListView->uChanged & LVIF_STATE) &&
(pNMListView->uNewState & LVIS_SELECTED))
{
int nItem = pNMListView->iItem;
// 取得項目資料(如主鍵 ID),通知從表視圖重新查詢
CString strKey = GetItemText(nItem, 0);
NotifyDetailViewRefresh(strKey);
}
*pResult = 0;
}
RefreshData(LPCTSTR szMasterKey)SELECT * FROM DetailTable WHERE MasterID = ?CRecordset::Requery() 而非重新 Open;必要時在從表資料量大時啟用分頁或虛擬模式。靜態巢狀分割器構建穩定的三視圖佈局,主框架轉發指標實現鬆耦合通訊,列表控件配合 LVN_ITEMCHANGED 完成主從聯動。此架構清晰、可維護,適合 MFC 應用中常見的主從表管理介面。