导航

单文档中动态更换多种视图

Posted on 2010-04-15 15:05  3DDreams  阅读(852)  评论(0编辑  收藏  举报

代码简介或代码解析:
 
       在一些情况下,应用程序有许多信息要显示,当一个窗口内显示不下时,VC提供的MDI应用程序可以解决这个问题,但是如果应用程序只是对单个文档,采用多种方式显示,则采用SDI更合适。那么,如何在单文档应用程序中实现多视图呢?缺省情况下,派生类的构造函数是pretected类型的,必须将它改为public类型,因为我们将会动态生成派生视图类并切换活动的视图。也可以一次生成所有的视图,但是这样造成系统资源的极大浪费。

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();              //调整框架窗口
}

 

【本代码共有2条评论信息】

--------------------------------------------------------------------------------
 
 2004-8-5 22:56:31  本站网友【网事蒙尘】发表评论23:如何在分割窗口隐藏分割条和其中一个窗格
如何在分割窗口隐藏分割条和其中一个窗格


笔者是一个VC的爱好者,对VC作界面也十分感兴趣,前一些时候看到有网友在网上问,如何隐藏分割窗口中的分割条和其

中一个窗格.我认为我所知道的结果都不尽人意,所以笔者就用一个模拟的方式实现了,其制作过程如下:

1、创建视图
在CMainFrame中定义 Cmydeiview *m_myview;//设定我们要隐藏时保留的是:Cmydeiview


BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{

m_split.CreateStatic(this,1,2);
m_split.CreateView(0,0,RUNTIME_CLASS(CFromView),CSize(100,200),pContext);
m_split.CreateView(0,1,RUNTIME_CLASS(Cmydeiview),CSize(100,200),pContext);


//下面的是关键之处,就是多创建一个视图
m_myview=(Cmydeiview*)CreateView(pContext,hzp_view_id);
m_myview->ShowWindow(false);
return true;
}


2、在菜单中加入两个选项用于控制视图的显视或是隐藏

void CMainFrame::OnMenuitem32771()
{//隐藏窗格
m_myview->SetDlgCtrlID(AFX_IDW_PANE_FIRST);
m_myview->ShowWindow(true);
m_split.ShowWindow(false);
this->RecalcLayout();


}

void CMainFrame::OnMenuitem32772()
{
//显视窗格
    m_myview->SetDlgCtrlID(hzp_view_id);
m_myview->ShowWindow(false);
m_split.ShowWindow(true);
this->RecalcLayout();

}

3、通过测试以上的作法是安全而且,实现容易的。
 
 
 2004-8-26 20:39:06  本站网友【lostgdi】发表评论30:
哪个开关函数有问题。
来个简单的实验:
在哪个函数的switch里插入一句AfxMessageBox("hehe");
case IDD_MULTIVIEW_FORM2 :
            pNewActiveView=(CView*)new CView2;
AfxMessageBox("hehe");
            break;
预期是afxmessagebox只执行一次的,现在却是两次。