一个程序窗口要显示不同网格或类型的内容。一般会通过标签控件切换。源代码工程下载地址:
这里在单文档工程中,通过分割视窗来实现显示不同的内容。效果如图
界面为一个SDI窗口,主框架窗口由一个静态的一行二列的分隔器窗口组成。
左列CLeftPaneView派生于CFormView,
右列CRightPaneFrame派生于CFrameWnd。
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext*
pContext)
{
// TODO: Add your specialized code here and/or call the base class
if (!m_wndSplitter.CreateStatic(this, 1, 2))
{
TRACE0("Failed to create splitter window\n");
return FALSE;
}
// Get the client rect first for calc left pane size
CRect rect;
GetClientRect(&rect);
// create the left tree view first.
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CLeftPaneView),
CSize(rect.Width()/3, 0), pContext))
{
TRACE0("Failed to create left pane view\n");
return FALSE;
}
// The right pane is a frame which and contain several different views.
// The is can be set to active or non-active
if (!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CRightPaneFrame),
CSize(0, 0), pContext))
{
TRACE0("Failed to create right pane frame\n");
return FALSE;
}
// Set the left pane as the active view
SetActiveView((CView*) m_wndSplitter.GetPane(0, 0));
return TRUE;
}
既然右边窗格是一个框架窗口,它可以创建CView的派生类,比如CFromView。
左边窗格是一个CFormView派生类,其中包含一个树视控件。
右边窗格OnCreateClient创建所有不同的视,并设置活动视。
同时,右边窗格的视也可以是分隔器窗口。
BOOL CRightPaneFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext*
pContext)
{
// TODO: Add your specialized code here and/or call the base class
m_pSplitterView = new CSplitterView;
m_pSplitterView->Create(NULL, NULL, 0L, CFrameWnd::rectDefault, this,
VIEW_SPLITTER, pContext);
SetActiveView(m_pSplitterView);
m_pSplitterView->ShowWindow(SW_SHOW);
m_pSplitterView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
m_pListCtrlView = new CListCtrlView;
((CView*) m_pListCtrlView)->Create(NULL, NULL, 0L, CFrameWnd::rectDefault,
this, VIEW_LISTCTRL, pContext);
m_pListCtrlView->ShowWindow(SW_HIDE);
m_pListCtrlView->SetDlgCtrlID(VIEW_LISTCTRL);
m_pEditView = new CEditView;
m_pEditView->Create(NULL, NULL, 0L, CFrameWnd::rectDefault, this,
VIEW_EDIT, pContext);
m_pEditView->ShowWindow(SW_HIDE);
m_pEditView->SetDlgCtrlID(VIEW_EDIT);
RecalcLayout();
return TRUE;
}
右边窗格的OnCreateClient必须返回TRUE,并调用RecalcLayout()。
当选择左边窗格的一个项目时,左边窗格调用右边窗格的成员SwithToView:
void CRightPaneFrame::SwitchToView(UINT nView)
{
CView* pOldActiveView = GetActiveView();
CView* pNewActiveView;
switch (nView)
{
case VIEW_SPLITTER:
pNewActiveView = (CView*) m_pSplitterView;
break;
case VIEW_LISTCTRL:
pNewActiveView = (CView*) m_pListCtrlView;
break;
case VIEW_EDIT:
pNewActiveView = (CView*) m_pEditView;
break;
}
// don't switch when views are the same
if (pOldActiveView == pNewActiveView) return;
SetActiveView(pNewActiveView);
pNewActiveView->ShowWindow(SW_SHOW);
pNewActiveView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
pOldActiveView->ShowWindow(SW_HIDE);
pOldActiveView->SetDlgCtrlID(m_nCurrentViewID);
m_nCurrentViewID = nView;
RecalcLayout();
}
切换代码非常讲究技巧,它隐藏了所有老的活动视,显示新的活动视,并设置当前窗口控件ID。
最后,左边窗格树视选择需要调用右边窗格的切换函数。
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext*
pContext)
{
.
.
.
CLeftPaneView* pLeftPaneView = (CLeftPaneView*)
m_wndSplitter.GetPane(0,0);
pLeftPaneView->m_pRightPaneFrame = (CRightPaneFrame*)
m_wndSplitter.GetPane(0,1);
.
.
.
}
void CLeftPaneView::OnSelchangedTree(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
UINT nView = 0;
HTREEITEM hSelectedItem = m_treeCtrl.GetSelectedItem();
if (hSelectedItem == m_hSplitterView)
nView = VIEW_SPLITTER;
else
if (hSelectedItem == m_hListCtrlView)
nView = VIEW_LISTCTRL;
else
if (hSelectedItem == m_hEditView)
nView = VIEW_EDIT;
if (nView) m_pRightPaneFrame->SwitchToView(nView);
*pResult = 0;
}
|