Outlook Style Splitter

Here is a another Outlook lookalike example source code.

The OutlookStyle application is an SDI window. The main frame consist of a
static splitter window with one row and two columns.

The left column CLeftPaneView is derived from CFormView and CRightPaneFrame
is derived from 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;
}


Since the right pane is a frame, it can have views created from any CViews
types such as CFromView.
The left pane is CFormView with a tree control in it which resize itself
during OnSize.

I have added several items to the tree and process the tree selection
change message.
Based on the tree selected, I call the right pane to switch views.

The right pane OnCreateClient creates all the different views and set one
to be the active view.
The views in the right pane can also be splitter windows.

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;
}


The right pane OnCreateClient must return TRUE and RecalcLayout().
The right pane member SwithToView is called by the left pane when an item
is selected.

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();
}


The switch code is tricky, it has to hide the old active view, show the new
active view and
set the current dialog control id.

Finally, the left pane tree selection needs to call the right pane switch
function.
The left pane needs a referrence to the right pane window.

When the main frame creates the left and right pane it sets the right pane
window pointer to
the left pane member.

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;
}


The left pane OnSelchangedTree checks the selected item for a match and
then call
the SwitchToView to change view on the right pane.

Download a sample project outlook_style.zip (58.7k)