分类: C/C++
2011-08-20 10:58:49
一. 参考的做法
1 首先利用资源编辑器新建4个对话框,在对话框中添加需要的控件,各个对话框的ID分别为IDD_MULTIVIEW_FORM,IDD_MULTIVIEW_FORM2,IDD_MULTIVIEW_FORM3,IDD_MULTIVIEW_FORM4
2 为每一个对话框创建一个CFormView类的派生类,分别为:CView1,CView2,CView3,CView4
3 在应用程序的初始化文件中用CView1替换原先的视图,这样程序启动后的缺省显示视图是CView1,修改后的部分代码如下:
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CMultiViewDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_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
// 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,我看见过有个前辈是这么做的,而且是可行的,我没有实践过,所以不发表评论。