VC项目开发之单文档多视图实现(整理) .

 

多视图是VC开发中经常要用到的技术之一,一般地实现单文档多视图有三种方式(1)通过视图分割的技术(使用CSplitterWnd实现),将窗口分割为多个部分,每个部分显示各自显示不同的视图,这种技术实现起来比较简单,并且相关的资料也很多。(2)通过一个文档关联多个视图,窗口显示整个视图。(3)有一个函数可以简单的实现视图间的切换。下面就简单的介绍一下这三种方式。

1. 通过视图分割的技术

这种方式比较简单,有很多资料。这里就不详细介绍了,我的博客前面有详细的介绍。

2. 通过一个文档关联多个视图,窗口显示整个视图。

下面通过一个工程给出详细的实习方式。

Step 1:使用VC++ 6.0新建一个Project,命名为:MultiView。除选择单文档属性外,一切使用“默认”方式。于是你可以获得五个类:CMainFrame ,CMultiViewApp,CMultiViewDoc,CMultiViewView,和CAboutDlg;

Step 2:新建一个新的视图View,添加一个新的MFC Class(Insert->New Class),基类为CView(或者CView的派生子类,如CEditView等)。类的名字为CAnotherView,这就是新的视图;并为CAnotherView添加GetDocument的实现:

CMultiViewDoc* CAnotherView::GetDocument()

{

    return (CMultiViewDoc*)m_pDocument;

}

Step 3:在CMultiViewApp添加成员变量记录这两个视图:

 private:

      CView* m_pFirstView;

      CView* m_pAnotherView;

 

 给程序菜单IDR_MAINFRAME添加一个菜单项目“视图”,该菜单项有两个子菜单“视图一”和“视图二”,添加相应函数(void CMultiViewApp:: OnShowFirstview()和void CMultiViewApp:: OnShowSecondview());  

Step 4:创建新的视图:在BOOL CMultiViewApp::InitInstance()中添加代码:

   …….

   //创建一个新的视图

    CView* m_pActiveView = ((CFrameWnd*)m_pMainWnd)->GetActiveView();

    m_pFirstView = m_pActiveView;    

    m_pAnotherView = new CAnotherView();

    //文档和视图关联

    CDocument* m_pDoc = ((CFrameWnd*)m_pMainWnd)->GetActiveDocument();

    CCreateContext context;

    context.m_pCurrentDoc = m_pDoc;

    //创建视图

    UINT m_IDFORANOTHERVIEW = AFX_IDW_PANE_FIRST + 1;

    CRect rect;

    m_pAnotherView->Create(NULL,NULL,WS_CHILD,rect,m_pMainWnd,

                        m_IDFORANOTHERVIEW,&context);

……

Step 5:现在已经创建了视图,并且都和文档关联起来了。现在要作的就是视图间的转换。在void CMultiViewApp:: OnShowFirstview()中添加实现代码:

void CMultiViewApp::OnShowFirstview()

{

    // TODO: Add your command handler code here

   UINT temp = ::GetWindowLong(m_pAnotherView->m_hWnd, GWL_ID);

   ::SetWindowLong(m_pAnotherView->m_hWnd, GWL_ID, ::GetWindowLong(m_pFirstView->m_hWnd, GWL_ID));

   ::SetWindowLong(m_pFirstView->m_hWnd, GWL_ID, temp);

    m_pAnotherView->ShowWindow(SW_HIDE);

    m_pFirstView->ShowWindow(SW_SHOW);

 

    ((CFrameWnd*)m_pMainWnd)->SetActiveView(m_pFirstView);

 

    ((CFrameWnd*) m_pMainWnd)->RecalcLayout();

 

   m_pFirstView->Invalidate();}

在void CMultiViewApp:: OnShowSecondview()中添加实现代码:

void CMultiViewApp::OnShowSecondview()

{

    // TODO: Add your command handler code here

   UINT temp = ::GetWindowLong(m_pAnotherView->m_hWnd, GWL_ID);

 

   ::SetWindowLong(m_pAnotherView->m_hWnd, GWL_ID, ::GetWindowLong(m_pFirstView->m_hWnd, GWL_ID));

 

   ::SetWindowLong(m_pFirstView->m_hWnd, GWL_ID, temp);

 

    m_pFirstView->ShowWindow(SW_HIDE);

 

    m_pAnotherView->ShowWindow(SW_SHOW);    

 

    ((CFrameWnd*)m_pMainWnd)->SetActiveView(m_pAnotherView);

 

    ((CFrameWnd*) m_pMainWnd)->RecalcLayout();

 

   m_pAnotherView->Invalidate();

}

 

Step 6:为了演示,这里将不同的视图给予一个标记,在CMultiViewView和CAnotherView的OnDraw方法中分别添加以下代码:

   pDC->TextOut(400,300,"First View");

    pDC->TextOut(400,320,pDoc->GetTitle());

   pDC->TextOut(400,300,"Another View");

 pDC->TextOut(400,320,pDoc->GetTitle());

至此就大功告成了,但是实现过程中有2点说明:

1) 实现中由于使用到相关的类,因此在必要的地方要include相关的头文件,这里省略;CAnotherView的默认构造函数是Protected的,需要将其改为Public,或者提供一个产生CAnotherView对象的方法(因要创建视图对象);

2) 这里给出的是一个示例代码,实际开发中可以通过参考实现获得自己想要实现的具体应用情况(例如视图类的不同、数量不同,更重要的还有业务逻辑的不同实现等);

3.通过一个简单的函数实现。

在CMainFrame中加入如下函数:

void CMainFrame::SwitchToView(int nForm)

{

    //CDocument* pDoc = GetActiveDocument();

    CView *pOldActiveView=GetActiveView();         //保存旧视图

    CView *pNewActiveView=(CView*)GetDlgItem(nForm);   //取得新视图

    if(pNewActiveView==NULL)

    {

        switch(nForm)

              //这些ID是对话框的标志符,但也可以用其他的标志

        {

        case IDD_PLANT_VIEW :

              pNewActiveView=(CView*)new CPlantView;

              break;

        case IDD_HSUB_VIEW :

              pNewActiveView=(CView*)new CHSubView;

              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_SHOWMAXIMIZED); //显示新的视图

    pOldActiveView->ShowWindow(SW_HIDE); //隐藏旧的视图

 

    pNewActiveView->GetDocument()->SetTitle("。。。。");

    if(pOldActiveView->GetRuntimeClass() ==RUNTIME_CLASS(CHSubView))

        pOldActiveView->SetDlgCtrlID(IDD_HSUB_VIEW);

 

    else if(pOldActiveView->GetRuntimeClass() ==RUNTIME_CLASS(CPlantView))

        pOldActiveView->SetDlgCtrlID(IDD_PLANT_VIEW);

 

    pNewActiveView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);

     delete pOldActiveView;   //删除旧视图

 

    RecalcLayout();       //调整框架窗口

}

这个函数很好用大家可以参考一下。其中IDD_HSUB_VIEW 等都是新建立的FormView,也就是继承了CFormView类的新类。注意将各个新类中的构造函数改成public,才能用此函数不出错。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值