Sometimes you just want to switch view classes under program control and you don't want to be bothered with a splitter window. The EX20C example is an SDI application that switches between CStringView and CHexView in response to selections on the View menu. Starting with what AppWizard generates, all you need to do is add two new menu commands and then add some code to the CMainFrame class. You also need to change the CStringView and CHexView constructors from protected to public.
The following two items have been added to the View menu in the IDR_MAINFRAME menu resource.
Caption | Command ID | CMainFrame Function |
St&ring View | ID_VIEW_STRINGVIEW | OnViewStringView |
&Hex View | ID_VIEW_HEXVIEW | OnViewHexView |
ClassWizard was used to add the command-handling functions (and corresponding update command UI handlers) to the CMainFrame class.
The CMainFrame class gets a new private helper function, SwitchToView, which is called from the two menu command handlers. The enum parameter tells the function which view to switch to. Here are the two added items in the MainFrm.h header file:
private: enum eView { STRING = 1, HEX = 2 }; void SwitchToView(eView nView);
The SwitchToView function (in MainFrm.cpp) makes some low-level MFC calls to locate the requested view and to activate it. Don't worry about how it works. Just adapt it to your own applications when you want the view- switching feature. Add the following code:
void CMainFrame::SwitchToView(eView nView) { CView* pOldActiveView = GetActiveView(); CView* pNewActiveView = (CView*) GetDlgItem(nView); if (pNewActiveView == NULL) { switch (nView) { case STRING: pNewActiveView = (CView*) new CStringView; break; case HEX: pNewActiveView = (CView*) new CHexView; break; } CCreateContext context; context.m_pCurrentDoc = pOldActiveView->GetDocument(); pNewActiveView->Create(NULL, NULL, WS_BORDER, CFrameWnd::rectDefault, this, nView, &context); pNewActiveView->OnInitialUpdate(); } SetActiveView(pNewActiveView); pNewActiveView->ShowWindow(SW_SHOW); pOldActiveView->ShowWindow(SW_HIDE); pOldActiveView->SetDlgCtrlID( pOldActiveView->GetRuntimeClass() == RUNTIME_CLASS(CStringView) ? STRING : HEX); pNewActiveView->SetDlgCtrlID(AFX_IDW_PANE_FIRST); RecalcLayout(); }
Finally, here are the menu command handlers and update command UI handlers that ClassWizard initially generated (along with message map entries and prototypes). The update command UI handlers test the current view's class.
void CMainFrame::OnViewStringView() { SwitchToView(STRING); } void CMainFrame::OnUpdateViewStringView(CCmdUI* pCmdUI) { pCmdUI->Enable( !GetActiveView()->IsKindOf(RUNTIME_CLASS(CStringView))); } void CMainFrame::OnViewHexView() { SwitchToView(HEX); } void CMainFrame::OnUpdateViewHexView(CCmdUI* pCmdUI) { pCmdUI->Enable( !GetActiveView()->IsKindOf(RUNTIME_CLASS(CHexView))); }
The EX20C application initially displays the CStringView view of the document. You can toggle between the CStringView and CHexView views by choosing the appropriate command from the View menu. Both views of the document are shown side by side in Figure 20-2.
Figure 20-2. The CStringView view and the CHexView view of the document.