MFC视图切换大全总结
添加时间:2013-8-8 点击量:
纯真视图之间的切换
单文档多视图切换是我在进修MFC中碰到的一个垂老难题目,在今天总算是一一了。我感觉视图切换分为三个等级,第一是在未切分窗格的景象下切换视图类;第二是在分别窗格的一个窗格内实验视图切换;第三是在分别窗格和未分别之间的切换和视图切换。
在MFC创建SDI的伊始,MFC默认的视图类是CView,若是CView满足你的需求,可以直接单击finish,若是你不想让CView成为你的默认视图类,你可以鄙人图这个处所批改。
若是你忘怀了批改默认的视图类这也没紧要,我们可以在代码中改变:
在App类里面有个函数叫InitInstance(),在这里面有一段代码
CSingleDocTemplate pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(Cprogram8Doc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CView1)); //这里更改你的默认视图类,重视不要忘怀包含头文件哦
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
说完了默认视图类的更改,我们如今进入主题。
1、起建你须要切换的视图类,AddClass进入或者创建一个控件然后AddClass创建控件接洽关系类,后者实用于Form之类的控件。
2、把握之处,比如菜单项单击、单击鼠标什么的,我是应用菜单项来切换窗口的
void CMainFrame::OnView1()
{
// TODO: Add your command handler code here
SwitchToForm(IDD_FORMVIEW1);
}
void CMainFrame::OnView2()
{
// TODO: Add your command handler code here
SwitchToForm(IDD_FORMVIEW2);
}
3、SwitchToForm这个函数首要用于视图切换
在这个函数中首要做以下几个动作:
1、获合适前视图类指针和须要转换的视图类指针,若是是第一次应用须要New一个,并且与文档类接洽关系;
2、改变活动视图;
3、显示新视图和隐蔽旧视图;
4、设置控件ID;
5、调剂框架视图。
void CMainFrame::SwitchToForm(int nForm)
{
CView pOldActiveView=GetActiveView(); //1
CView pNewActiveView=(CView)GetDlgItem(nForm);
if(NULL==pNewActiveView)
{
switch(nForm)
{
case IDD_FORMVIEW1:
pNewActiveView=(CView)new CView1;
break;
case IDD_FORMVIEW2:
pNewActiveView=(CView)new CView2;
break;
case IDD_FORMVIEW3:
pNewActiveView=(CView)new CView3;
break;
case IDD_FORMVIEW4:
pNewActiveView=(CView)new CView4;
break;
default:
break;
}
CCreateContext context;
context.m_pCurrentDoc=pOldActiveView->GetDocument();
pNewActiveView->Create(NULL,NULL,WS_CHILD | WS_BORDER,CFrameWnd::rectDefault,this,nForm,&context);
pNewActiveView->UpdateData();
}
SetActiveView(pNewActiveView); //2
pNewActiveView->ShowWindow(SW_SHOW); //3
pOldActiveView->ShowWindow(SW_HIDE);
if(pOldActiveView->GetRuntimeClass()==RUNTIME_CLASS(CView1)) //4
pOldActiveView->SetDlgCtrlID(IDD_FORMVIEW1);
else if(pOldActiveView->GetRuntimeClass()==RUNTIME_CLASS(CView2))
pOldActiveView->SetDlgCtrlID(IDD_FORMVIEW2);
else if(pOldActiveView->GetRuntimeClass()==RUNTIME_CLASS(CView3))
pOldActiveView->SetDlgCtrlID(IDD_FORMVIEW3);
else if(pOldActiveView->GetRuntimeClass()==RUNTIME_CLASS(CView4))
pOldActiveView->SetDlgCtrlID(IDD_FORMVIEW4);
pNewActiveView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
RecalcLayout(); //5
}
在看网上其他人的帖子的时辰发明在RecalcLayout(); 前面还要加一句 pOldActiveView;我本身感觉如许有些浪费资料,视图类创建完成了隐蔽起来,用的时辰从头显示。如许的办法应当比每次应用都要创建好一些。小弟不才,有评论辩论的伴侣可以接洽我。
带有分别窗格的视图切换
切换视图第二层就是带有分别窗格的视图切换
分别窗格的视图切换,我感觉难点是不轻易在有限区域进行视图切换。
1、起首分别窗格,这里我不久不多申明,详情看下面链接;
2、再给每个视图一个独一的ID号;
m_splitter.CreateStatic(this,1,2);
m_splitter.CreateView(0,0,RUNTIME_CLASS(CTree1),CSize(100,100),pContext);
m_splitter.CreateView(0,1,RUNTIME_CLASS(CForm1),CSize(100,100),pContext);
CWnd pWnd=m_splitter.GetPane(0,1);
m_pViews[0]=(CView)m_splitter.GetPane(0,1);
pWnd->SetDlgCtrlID(IDD_FORM1);
pWnd->ShowWindow(SW_HIDE);
m_splitter.CreateView(0,1,RUNTIME_CLASS(CForm2),CSize(100,100),pContext);
pWnd=m_splitter.GetPane(0,1);
m_pViews[1]=(CView)m_splitter.GetPane(0,1);
pWnd->SetDlgCtrlID(m_splitter.IdFromRowCol(0,1));
pWnd->ShowWindow(SW_SHOW);
RedrawWindow();
return true;
注:我这里CreateView一个新视图,就覆盖掉前一个视图,终极显示的是最后一个视图,前面的视图只是隐蔽起来,比及应用的时辰显示出来就好了。返回值要覆盖返回到基类的语句return CFrameWndEx::OnCreateClient(lpcs, pContext);将这句话注解,然后return true;
3、在哪里激活切换功能本身设计,我应用的是菜单;
4、响应首要包含下面几个步调:
1、起首获得窗格中的当前视图;
2、应用IsKindOf断定这个类是否是将要切换到的类;
3、获得框架长宽和窗格长宽;
CView pView=(CView)m_splitter.GetPane(0,1); //1
m_bTest=pView->IsKindOf(RUNTIME_CLASS(CForm2)); //2
CRect rcFrame,rcClient; //3
m_splitter.GetClientRect(&rcClient);
GetClientRect(&rcFrame);
上方的全部是筹办工作,下面才是真正的切换;
4、删除原有视图
5、创建当前视图
6、调剂框架
if(m_bTest)
{
m_splitter.DeleteView(0,1);
m_splitter.CreateView(0,1,RUNTIME_CLASS(CForm1),CSize(rcClient.Width(),rcFrame.Height()),NULL);
m_splitter.RecalcLayout();
}
else
{
m_splitter.DeleteView(0,1);
m_splitter.CreateView(0,1,RUNTIME_CLASS(CForm2),CSize(rcClient.Width(),rcFrame.Height()),NULL);
m_splitter.RecalcLayout();
}
细心一看,貌似这个还要比纯真视图切换还要简单一些,这也没办法,CSplitterWnd供给了这么一个便捷的办法。
带分别视图与未分别视图之间的切换
这个是三部曲中我认为最难的,并不是说法度有多么难,只是想到这个切分体式格式真的不轻易,今天就把这三部曲的最后一曲分享给大师,也为互联网做一点供献。
起首说一下法度的思惟,为分别窗口层专门自力创建一个基于CFrameWnd的类,然后在这里面写分别视图的代码,再与其他未分别的视图类进行切换。
下面我们来看一下实现的过程:
1、创建一个基于CFrameWnd的派生类CSplitterFrame;
2、添加要填充沛割窗口的视图类和与分别视图切换的视图类;
3、为这个派生类重载OnCreateClient函数,机关分别视图
m_Splitter.CreateStatic(this,1,2);
m_Splitter.CreateView(0,0,RUNTIME_CLASS(CLeftTree),CSize(300,0),pContext);
m_Splitter.CreateView(0,1,RUNTIME_CLASS(CRightList),CSize(300,0),pContext);
return true;
这里我不说了然,想必大师都很熟悉了,这里我要说一点我本身犯过的错误。我底本想在这里GetClientRect获得窗口大小,但失败了,左思右想不熟悉打听,后来才发明,这又不是CMainFrame,所以底子不克不及获得,如果用API函数。
4、在CMainFrame类里面添加框架和视图类指针变量
CSplitterFrame m_pSplitterFrame; //分别视图框架指针
CView m_pView; //零丁视图类,基于CView类
CView m_pForm; //零丁视图类,基于CFormView类
int m_nCurrentID; //记录当前视图
5、在CMainFrame类里面重载OnCreateClient函数,创建视图及分别框架
CRect rcClient;
GetClientRect(&rcClient);
m_pView=new CViewShow;
m_pView->Create(NULL,NULL,AFX_WS_DEFAULT_VIEW &~WS_BORDER,rcClient,this,NULL,pContext);
m_pView->ShowWindow(SW_SHOW);
m_pView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
pContext->m_pNewViewClass=(CRuntimeClass)m_pView; //设置默认视图类
m_pForm=new CFormShow;
m_pForm->Create(NULL,NULL,AFX_WS_DEFAULT_VIEW &~WS_BORDER,rcClient,this,IDD_FORMSHOW,pContext);
m_pForm->ShowWindow(SW_HIDE);
m_pSplitterFrame=new CSplitterFrame;
m_pSplitterFrame->Create(NULL,NULL,AFX_WS_DEFAULT_VIEW &~WS_BORDER,rcClient,this,NULL,0,pContext);
m_pSplitterFrame->ShowWindow(SW_HIDE);
return true;
6、创建视图切换函数
bool CMainFrame::Switch(int nID)
{
if(nID==m_nCurrentID)
return false;
switch(nID)
{
case IDD_FORMSHOW:
m_pForm->ShowWindow(SW_SHOW);
m_pForm->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
m_pView->ShowWindow(SW_HIDE);
m_pView->SetDlgCtrlID(AFX_IDW_PANE_FIRST+2);
m_pSplitterFrame->ShowWindow(SW_HIDE);
m_pSplitterFrame->SetDlgCtrlID(AFX_IDW_PANE_FIRST+1);
m_nCurrentID=IDD_FORMSHOW;
break;
case AFX_IDW_PANE_FIRST+1:
m_pSplitterFrame->ShowWindow(SW_SHOW);
m_pSplitterFrame->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
m_pForm->ShowWindow(SW_HIDE);
m_pForm->SetDlgCtrlID(IDD_FORMSHOW);
m_pView->ShowWindow(SW_HIDE);
m_pView->SetDlgCtrlID(AFX_IDW_PANE_FIRST+2);
m_nCurrentID=AFX_IDW_PANE_FIRST+1;
break;
case AFX_IDW_PANE_FIRST+2:
m_pView->ShowWindow(SW_SHOW);
m_pView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
m_pForm->ShowWindow(SW_HIDE);
m_pForm->SetDlgCtrlID(IDD_FORMSHOW);
m_pSplitterFrame->ShowWindow(SW_HIDE);
m_pSplitterFrame->SetDlgCtrlID(AFX_IDW_PANE_FIRST+1);
m_nCurrentID=AFX_IDW_PANE_FIRST+2;
break;
default:
break;
}
RecalcLayout();
return true;
}
7、创建调用办法
void CMainFrame::OnForm()
{
// TODO: Add your command handler code here
Switch(IDD_FORMSHOW);
}
void CMainFrame::OnView()
{
// TODO: Add your command handler code here
Switch(AFX_IDW_PANE_FIRST+2);
}
void CMainFrame::OnSplitter()
{
// TODO: Add your command handler code here
Switch(AFX_IDW_PANE_FIRST+1);
}
我俩之间有着强烈的吸引力。短短几个小时后,我俩已经明白:我们的心是一个整体的两半,我俩的心灵是孪生兄妹,是知己。她让我感到更有活力,更完美,更幸福。即使她不在我身边,我依然还是感到幸福,因为她总是以这样或者那样的方式出现在我心头。——恩里克·巴里奥斯《爱的文明》
纯真视图之间的切换
单文档多视图切换是我在进修MFC中碰到的一个垂老难题目,在今天总算是一一了。我感觉视图切换分为三个等级,第一是在未切分窗格的景象下切换视图类;第二是在分别窗格的一个窗格内实验视图切换;第三是在分别窗格和未分别之间的切换和视图切换。
在MFC创建SDI的伊始,MFC默认的视图类是CView,若是CView满足你的需求,可以直接单击finish,若是你不想让CView成为你的默认视图类,你可以鄙人图这个处所批改。
若是你忘怀了批改默认的视图类这也没紧要,我们可以在代码中改变:
在App类里面有个函数叫InitInstance(),在这里面有一段代码
CSingleDocTemplate pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(Cprogram8Doc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CView1)); //这里更改你的默认视图类,重视不要忘怀包含头文件哦
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
说完了默认视图类的更改,我们如今进入主题。
1、起建你须要切换的视图类,AddClass进入或者创建一个控件然后AddClass创建控件接洽关系类,后者实用于Form之类的控件。
2、把握之处,比如菜单项单击、单击鼠标什么的,我是应用菜单项来切换窗口的
void CMainFrame::OnView1()
{
// TODO: Add your command handler code here
SwitchToForm(IDD_FORMVIEW1);
}
void CMainFrame::OnView2()
{
// TODO: Add your command handler code here
SwitchToForm(IDD_FORMVIEW2);
}
3、SwitchToForm这个函数首要用于视图切换
在这个函数中首要做以下几个动作:
1、获合适前视图类指针和须要转换的视图类指针,若是是第一次应用须要New一个,并且与文档类接洽关系;
2、改变活动视图;
3、显示新视图和隐蔽旧视图;
4、设置控件ID;
5、调剂框架视图。
void CMainFrame::SwitchToForm(int nForm)
{
CView pOldActiveView=GetActiveView(); //1
CView pNewActiveView=(CView)GetDlgItem(nForm);
if(NULL==pNewActiveView)
{
switch(nForm)
{
case IDD_FORMVIEW1:
pNewActiveView=(CView)new CView1;
break;
case IDD_FORMVIEW2:
pNewActiveView=(CView)new CView2;
break;
case IDD_FORMVIEW3:
pNewActiveView=(CView)new CView3;
break;
case IDD_FORMVIEW4:
pNewActiveView=(CView)new CView4;
break;
default:
break;
}
CCreateContext context;
context.m_pCurrentDoc=pOldActiveView->GetDocument();
pNewActiveView->Create(NULL,NULL,WS_CHILD | WS_BORDER,CFrameWnd::rectDefault,this,nForm,&context);
pNewActiveView->UpdateData();
}
SetActiveView(pNewActiveView); //2
pNewActiveView->ShowWindow(SW_SHOW); //3
pOldActiveView->ShowWindow(SW_HIDE);
if(pOldActiveView->GetRuntimeClass()==RUNTIME_CLASS(CView1)) //4
pOldActiveView->SetDlgCtrlID(IDD_FORMVIEW1);
else if(pOldActiveView->GetRuntimeClass()==RUNTIME_CLASS(CView2))
pOldActiveView->SetDlgCtrlID(IDD_FORMVIEW2);
else if(pOldActiveView->GetRuntimeClass()==RUNTIME_CLASS(CView3))
pOldActiveView->SetDlgCtrlID(IDD_FORMVIEW3);
else if(pOldActiveView->GetRuntimeClass()==RUNTIME_CLASS(CView4))
pOldActiveView->SetDlgCtrlID(IDD_FORMVIEW4);
pNewActiveView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
RecalcLayout(); //5
}
在看网上其他人的帖子的时辰发明在RecalcLayout(); 前面还要加一句 pOldActiveView;我本身感觉如许有些浪费资料,视图类创建完成了隐蔽起来,用的时辰从头显示。如许的办法应当比每次应用都要创建好一些。小弟不才,有评论辩论的伴侣可以接洽我。
带有分别窗格的视图切换
切换视图第二层就是带有分别窗格的视图切换
分别窗格的视图切换,我感觉难点是不轻易在有限区域进行视图切换。
1、起首分别窗格,这里我不久不多申明,详情看下面链接;
2、再给每个视图一个独一的ID号;
m_splitter.CreateStatic(this,1,2);
m_splitter.CreateView(0,0,RUNTIME_CLASS(CTree1),CSize(100,100),pContext);
m_splitter.CreateView(0,1,RUNTIME_CLASS(CForm1),CSize(100,100),pContext);
CWnd pWnd=m_splitter.GetPane(0,1);
m_pViews[0]=(CView)m_splitter.GetPane(0,1);
pWnd->SetDlgCtrlID(IDD_FORM1);
pWnd->ShowWindow(SW_HIDE);
m_splitter.CreateView(0,1,RUNTIME_CLASS(CForm2),CSize(100,100),pContext);
pWnd=m_splitter.GetPane(0,1);
m_pViews[1]=(CView)m_splitter.GetPane(0,1);
pWnd->SetDlgCtrlID(m_splitter.IdFromRowCol(0,1));
pWnd->ShowWindow(SW_SHOW);
RedrawWindow();
return true;
注:我这里CreateView一个新视图,就覆盖掉前一个视图,终极显示的是最后一个视图,前面的视图只是隐蔽起来,比及应用的时辰显示出来就好了。返回值要覆盖返回到基类的语句return CFrameWndEx::OnCreateClient(lpcs, pContext);将这句话注解,然后return true;
3、在哪里激活切换功能本身设计,我应用的是菜单;
4、响应首要包含下面几个步调:
1、起首获得窗格中的当前视图;
2、应用IsKindOf断定这个类是否是将要切换到的类;
3、获得框架长宽和窗格长宽;
CView pView=(CView)m_splitter.GetPane(0,1); //1
m_bTest=pView->IsKindOf(RUNTIME_CLASS(CForm2)); //2
CRect rcFrame,rcClient; //3
m_splitter.GetClientRect(&rcClient);
GetClientRect(&rcFrame);
上方的全部是筹办工作,下面才是真正的切换;
4、删除原有视图
5、创建当前视图
6、调剂框架
if(m_bTest)
{
m_splitter.DeleteView(0,1);
m_splitter.CreateView(0,1,RUNTIME_CLASS(CForm1),CSize(rcClient.Width(),rcFrame.Height()),NULL);
m_splitter.RecalcLayout();
}
else
{
m_splitter.DeleteView(0,1);
m_splitter.CreateView(0,1,RUNTIME_CLASS(CForm2),CSize(rcClient.Width(),rcFrame.Height()),NULL);
m_splitter.RecalcLayout();
}
细心一看,貌似这个还要比纯真视图切换还要简单一些,这也没办法,CSplitterWnd供给了这么一个便捷的办法。
带分别视图与未分别视图之间的切换
这个是三部曲中我认为最难的,并不是说法度有多么难,只是想到这个切分体式格式真的不轻易,今天就把这三部曲的最后一曲分享给大师,也为互联网做一点供献。
起首说一下法度的思惟,为分别窗口层专门自力创建一个基于CFrameWnd的类,然后在这里面写分别视图的代码,再与其他未分别的视图类进行切换。
下面我们来看一下实现的过程:
1、创建一个基于CFrameWnd的派生类CSplitterFrame;
2、添加要填充沛割窗口的视图类和与分别视图切换的视图类;
3、为这个派生类重载OnCreateClient函数,机关分别视图
m_Splitter.CreateStatic(this,1,2);
m_Splitter.CreateView(0,0,RUNTIME_CLASS(CLeftTree),CSize(300,0),pContext);
m_Splitter.CreateView(0,1,RUNTIME_CLASS(CRightList),CSize(300,0),pContext);
return true;
这里我不说了然,想必大师都很熟悉了,这里我要说一点我本身犯过的错误。我底本想在这里GetClientRect获得窗口大小,但失败了,左思右想不熟悉打听,后来才发明,这又不是CMainFrame,所以底子不克不及获得,如果用API函数。
4、在CMainFrame类里面添加框架和视图类指针变量
CSplitterFrame m_pSplitterFrame; //分别视图框架指针
CView m_pView; //零丁视图类,基于CView类
CView m_pForm; //零丁视图类,基于CFormView类
int m_nCurrentID; //记录当前视图
5、在CMainFrame类里面重载OnCreateClient函数,创建视图及分别框架
CRect rcClient;
GetClientRect(&rcClient);
m_pView=new CViewShow;
m_pView->Create(NULL,NULL,AFX_WS_DEFAULT_VIEW &~WS_BORDER,rcClient,this,NULL,pContext);
m_pView->ShowWindow(SW_SHOW);
m_pView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
pContext->m_pNewViewClass=(CRuntimeClass)m_pView; //设置默认视图类
m_pForm=new CFormShow;
m_pForm->Create(NULL,NULL,AFX_WS_DEFAULT_VIEW &~WS_BORDER,rcClient,this,IDD_FORMSHOW,pContext);
m_pForm->ShowWindow(SW_HIDE);
m_pSplitterFrame=new CSplitterFrame;
m_pSplitterFrame->Create(NULL,NULL,AFX_WS_DEFAULT_VIEW &~WS_BORDER,rcClient,this,NULL,0,pContext);
m_pSplitterFrame->ShowWindow(SW_HIDE);
return true;
6、创建视图切换函数
bool CMainFrame::Switch(int nID)
{
if(nID==m_nCurrentID)
return false;
switch(nID)
{
case IDD_FORMSHOW:
m_pForm->ShowWindow(SW_SHOW);
m_pForm->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
m_pView->ShowWindow(SW_HIDE);
m_pView->SetDlgCtrlID(AFX_IDW_PANE_FIRST+2);
m_pSplitterFrame->ShowWindow(SW_HIDE);
m_pSplitterFrame->SetDlgCtrlID(AFX_IDW_PANE_FIRST+1);
m_nCurrentID=IDD_FORMSHOW;
break;
case AFX_IDW_PANE_FIRST+1:
m_pSplitterFrame->ShowWindow(SW_SHOW);
m_pSplitterFrame->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
m_pForm->ShowWindow(SW_HIDE);
m_pForm->SetDlgCtrlID(IDD_FORMSHOW);
m_pView->ShowWindow(SW_HIDE);
m_pView->SetDlgCtrlID(AFX_IDW_PANE_FIRST+2);
m_nCurrentID=AFX_IDW_PANE_FIRST+1;
break;
case AFX_IDW_PANE_FIRST+2:
m_pView->ShowWindow(SW_SHOW);
m_pView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
m_pForm->ShowWindow(SW_HIDE);
m_pForm->SetDlgCtrlID(IDD_FORMSHOW);
m_pSplitterFrame->ShowWindow(SW_HIDE);
m_pSplitterFrame->SetDlgCtrlID(AFX_IDW_PANE_FIRST+1);
m_nCurrentID=AFX_IDW_PANE_FIRST+2;
break;
default:
break;
}
RecalcLayout();
return true;
}
7、创建调用办法
void CMainFrame::OnForm()
{
// TODO: Add your command handler code here
Switch(IDD_FORMSHOW);
}
void CMainFrame::OnView()
{
// TODO: Add your command handler code here
Switch(AFX_IDW_PANE_FIRST+2);
}
void CMainFrame::OnSplitter()
{
// TODO: Add your command handler code here
Switch(AFX_IDW_PANE_FIRST+1);
}