一. 参考的做法1 首先利用资源编辑器新建4个对话框,在对话框中添加需要的控件,各个对话框的ID分别为IDD_MULTIVIEW_FORM,IDD_MULTIVIEW_FORM2,IDD_MULTIVIEW_FORM3,IDD_MULTIVIEW_FORM42 为每一个对话框创建一个CFormView类的派生类,分别为:CView1,CView2,CView3,CView43 在应用程序的初始化文件中用CView1替换原先的视图,这样程序启动后的缺省显示视图是CView1,修改后的部分代码如下:CSingleDocTemplate* pDocTemplate;pDocTemplate = new CSingleDocTemplate(IDR_MAINFRAME,RUNTIME_CLASS(CMultiViewDoc),RUNTIME_CLASS(CMainFrame), // main SDI frame windowRUNTIME_CLASS(CView1));AddDocTemplate(pDocTemplate);4 利用资源编辑器,添加几个菜单,并添加相应的消息处理函数:void CMainFrame::OnViewView1() {SwitchToForm(IDD_MULTIVIEW_FORM); }void CMainFrame::OnViewView2() {SwitchToForm(IDD_MULTIVIEW_FORM2); }void CMainFrame::OnViewView3() {SwitchToForm(IDD_MULTIVIEW_FORM3); }void CMainFrame::OnViewView4() {SwitchToForm(IDD_MULTIVIEW_FORM4); }在SDI 中CFrame的派生类即CMainFrame控制着所有的视图,而且它允许用户通过消息处理进行视图的切换。进行视图切换的原理很简单,只是断开和旧视 图的连接并把他删除,创建一个新视图,将文档和它相连,设置几个标志,然后显示新视图,SwitchToForm函数是进行视图切换的代码函数。void CMainFrame::SwitchToForm(int nForm){ //CDocument* pDoc = GetActiveDocument(); CView *pOldActiveView=GetActiveView(); //保存旧视图 CView *pNewActiveView=(CView*)GetDlgItem(nForm); //取得新视图 if(pNewActiveView==NULL) { switch(nForm) //这些ID是对话框的标志符,但也可以用其他的标志 { case IDD_MULTIVIEW_FORM : pNewActiveView=(CView*)new CView1; break; case IDD_MULTIVIEW_FORM2 : pNewActiveView=(CView*)new CView2; break; case IDD_MULTIVIEW_FORM3 : pNewActiveView=(CView*)new CView3; break; case IDD_MULTIVIEW_FORM4 : pNewActiveView=(CView*)new CView4; break; } CCreateContext context; //将文挡和视图相连 context.m_pCurrentDoc=pOldActiveView->GetDocument();pNewActiveView->Create(NULL, NULL, WS_BORDER|WS_CHILD , CFrameWnd::rectDefault, this, nForm, &context); pNewActiveView->OnInitialUpdate(); } SetActiveView(pNewActiveView); //改变活动的视图 pNewActiveView->ShowWindow(SW_SHOW); //显示新的视图 pOldActiveView->ShowWindow(SW_HIDE); //隐藏旧的视图 if(pOldActiveView->GetRuntimeClass() ==RUNTIME_CLASS(CView1))pOldActiveView->SetDlgCtrlID(IDD_MULTIVIEW_FORM);else if(pOldActiveView->GetRuntimeClass() ==RUNTIME_CLASS(CView2))pOldActiveView->SetDlgCtrlID(IDD_MULTIVIEW_FORM2);else if(pOldActiveView->GetRuntimeClass() ==RUNTIME_CLASS(CView3))pOldActiveView->SetDlgCtrlID(IDD_MULTIVIEW_FORM3);else if(pOldActiveView->GetRuntimeClass() ==RUNTIME_CLASS(CView4))pOldActiveView->SetDlgCtrlID(IDD_MULTIVIEW_FORM4); pNewActiveView->SetDlgCtrlID(AFX_IDW_PANE_FIRST); delete pOldActiveView; //删除旧视图RecalcLayout(); //调整框架窗口}二.我的做法
// 普通视图和分栏视图的转换
CLogRcd::RecordLog("@ CMainFrame::OnViewAnalysis", MESSAGE_INVOKE);
CView *pOldView = GetActiveView();
// Must be switch from the record view and an opened record is available if (pOldView->IsKindOf(RUNTIME_CLASS(CEcmRecordView)) == FALSE || !m_bOpendRecord) return;
DWORD dwWaveWndWidth = ::GetSystemMetrics(SM_CXFULLSCREEN)/2; DWORD dwMapWndHeight = ::GetSystemMetrics(SM_CYFULLSCREEN)/2; CCreateContext cc; cc.m_pCurrentDoc = GetActiveDocument(); cc.m_pLastView = pOldView;
if (m_wndSplitter.GetColumnCount() == 0) // splitter has not be created { if (!m_wndSplitter.CreateStatic(this, 1, 2)) { TRACE("CMainFrame::OnViewAnalysis create splitter 0 static failed/n"); return; } }
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CEcmWaveView), CSize(dwWaveWndWidth, 0), &cc)) { TRACE("CMainFrame::OnViewAnalysis create wave view failed/n"); m_wndSplitter.DestroyWindow(); return; }
if (m_wndSplitter1.GetRowCount() == 0) // splitter1 has not be created { if (!m_wndSplitter1.CreateStatic(&m_wndSplitter, 2, 1, WS_CHILD|WS_VISIBLE, m_wndSplitter.IdFromRowCol(0, 1))) { TRACE("CMainFrame::OnViewAnalysis create splitter 1 static failed/n"); return; } }
if (!m_wndSplitter1.CreateView(0, 0, RUNTIME_CLASS(CEcmMapView), CSize(0, dwMapWndHeight), &cc)) { TRACE("CMainFrame::OnViewAnalysis create map view failed/n"); m_wndSplitter1.DestroyWindow(); return; }
if (!m_wndSplitter1.CreateView(1, 0, RUNTIME_CLASS(CEcmPropertyView), CSize(0, 0), &cc)) { TRACE("CMainFrame::OnViewAnalysis create electrode view failed/n"); m_wndSplitter1.DestroyWindow(); return; } CEcmUIDoc *pDoc = (CEcmUIDoc *)GetActiveDocument(); pDoc->m_paraData.pMapView = (CEcmMapView *)(m_wndSplitter1.GetPane(0, 0));
pDoc->RemoveView(pOldView); pOldView->ShowWindow(SW_HIDE); pOldView->DestroyWindow();
SetActiveView((CView *)m_wndSplitter.GetPane(0, 0)); // set wave view window as active one RecalcLayout();
m_wndSplitter.RecalcLayout(); // XX m_wndSplitter1.RecalcLayout(); // XX SetWindowText("Epicardial Mapping System User Interface : Analysing ...");
m_wndSplitter.ShowWindow(SW_NORMAL); m_wndSplitter1.ShowWindow(SW_NORMAL);
// 普通视和普通视的转换
CLogRcd::RecordLog("@ CMainFrame::OnViewSample", MESSAGE_INVOKE);
CView *pOldView = GetActiveView(); CEcmUIDoc *pDoc = static_cast<CEcmUIDoc *>(GetActiveDocument()); // Must be switch from the record view and an opened record is available if (pOldView->IsKindOf(RUNTIME_CLASS(CEcmRecordView)) == FALSE || !m_bOpendRecord) return;
// new a new CEcmSampleView CEcmSampleView *pNewView = new CEcmSampleView;
pNewView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, rectDefault, this, AFX_IDW_PANE_FIRST+1, NULL);
// switch view ID for further RecalcLayout int iNewViewID = pNewView->GetDlgCtrlID(); pNewView->SetDlgCtrlID(AFX_IDW_PANE_FIRST); pOldView->SetDlgCtrlID(iNewViewID);
// attach view to document pDoc->AddView(pNewView); pDoc->RemoveView(pOldView); SetActiveView(pNewView);
pNewView->ShowWindow(SW_SHOW); pOldView->ShowWindow(SW_HIDE); pNewView->OnInitialUpdate();
// redraw mainframe client area RecalcLayout(); SetWindowText("Epicardial Mapping System User Interface : Sampling ...");
三.说在最后 上面的方法只适用于SDI的App,对于MDI的做法是new一个DocTemplate出来,代替原来的DocTemplate,我看见过有个前辈是这么做的,而且是可行的,我没有实践过,所以不发表评论。
