【交互】单文档多视图代码分析

一、代码实现

       1、从View类派生3个视图类

       2、 CMainFrame中添加 CSplitterWnd m_right; CSplitterWnd m_left;//要分割的窗口

       3、代码实现如下:

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) 
{
	// TODO: Add your specialized code here and/or call the base class

	m_left.CreateStatic(this,1,2);//创建类名为MDI42窗口
	
	m_left.CreateView(0,0,RUNTIME_CLASS(CLeftView),CSize(180,550),pContext);//创建子窗口左边视图view42
	//CreateView里面会关联到当前文档当中去
	m_right.CreateStatic(&m_left,2,1,WS_CHILD | WS_VISIBLE,m_left.IdFromRowCol(0,1));//创建子窗口右边MDI42
	m_right.CreateView(0,0,RUNTIME_CLASS(CRightView),CSize(100,350),pContext);//创建右MDI42子窗口上面视图view42
	m_right.CreateView(1,0,RUNTIME_CLASS(CBottomView),CSize(100,300),pContext);//创建右MDI42子窗口下视图view42
	return TRUE;
//	return CFrameWnd::OnCreateClient(lpcs, pContext);//屏蔽原来的CView类,如果不屏蔽,则会创建ID号一样为AFX_IDW_PANE_FIRST的窗口,说明同层子窗口id是可以相同的
}

       4、窗口关系分析(父窗口、子窗口)

        第一级: CMainFrame
        第二级:CSplitterWnd m_left (AfxMDIFrame42d)   、状态栏statusbar32、4个AfxControlBar42d
        第三级(m_left):CSplitterWnd m_right (AfxMDIFrame42d)、AfxFrameOrView42d(C**View类)
        第四级(m_right):AfxFrameOrView42d(C**View类)、AfxFrameOrView42d(C**View类)       

二、原理分析

       1、窗口类派生关系
       CSplitterWnd:CWnd、C**View : CView

       2、创建分析

       CreateView时,有一个pContext->m_pCurrentDoc,View在创建之后,会将当前View类对象成员遍历m_pDocument赋值m_pCurrentDoc,同时将该View对象指针加入到m_pCurrentDoc中视图链表中。

       Q1、既然加入了视图链表中,如何实现CFrameWnd::m_ActiveView为活动视图呢?
                鼠标点击各个视图窗口,会发送一个WM_MOUSEACTIVATE消息给CView::OnMouseActivate消息,然后它会将view的this指针保存到CMainFrame的 m_ActiveView中。WM_LBUTTONDOWN稍后发送。
               

     CFrameWnd* pParentFrame = GetParentFrame();
{
     CWnd* pParentWnd = GetParent();  // start with one parent up
        while (pParentWnd != NULL)
     	{
  	    if (pParentWnd->IsFrameWnd())// CSpliterWnd派生于CWnd,而CMainFrame派生于CFrameWnd,对于上面m_left中的CBottomView而言,首先获得的是CSplitterWnd,但是它不是派生于CFrameWnd,继续往上找框架类。
//CWnd::IsFrameWnd() return FALSE,CFrameWnd::IsFrameWnd()return TRUE
   	       return (CFrameWnd*)pParentWnd;
  	    pParentWnd = pParentWnd->GetParent();
 	}
}

      pParentFrame->GetActiveView();//获取当前框架的m_ActiveView类
     //然后再验证是不是CView是不是m_ActiveView,是就再激活一次
      pParentFrame->SetActiveView(this);//不是,就保存到m_ActiveView中

       CSplitterWnd::GetActivePane()也是这样的方式,基本一样。

       可以在CView::OnMouseActivate()下断点,在调试运行。

       Q2、如果C**View派生于CEditView类,Edit控件是何时创建?
                当new 一个CEditView时,构造函数CEditView::CEditView() : CCtrlView(_T("EDIT"), NULL),这样就可在CCtrlView中创建Edit控件,调用pView-CreateEx("Edit"),就将CEditView关联了Edit控件窗口。
       3、位置分析
             创建窗口之后,一般不会去设置它的位置,现在创建一个窗口,OnCreate消息内创建其子窗口。

             一旦窗口位置改变,系统发送WM_SIZE消息,每个窗口,接受到OnSize(),里面一般会设置它的子窗口的位置。设置之后,子窗口收到WM_SIZE消息,由它来设置自身的位置。CView不处理OnSize消息。

       4、MFC框架图

        

        类图显示了MFC框架结构,不同的文档模板有不用的菜单资源。CFramWnd中有一个m_pAcitveView,可获得当前活动视图,通过它可以获得当前活动文档m_pActiveDocment。

        当文件点击保存时,CMainFrame收到OnFileSave消息,然后pActiveView、pDocument、CMainFrame、CWinApp顺序处理,如果要保存多个文档,则重载OnSaveDocument(LPCTSTR lpszPathName),写入自己的保存数据的函数。

参考:1、如何在MFC单文档中创建多视图

2、建立单文档多视图

3、MFC切割窗口

4、单文档实现多视图

5、VC++ 6.0使用CSplitterWnd类分割窗体,拆分窗体改变分隔条的宽度

6、使用CSplitterWnd实现拆分窗口(多视图显示)

7、用Win32实现类似MFC中Draw3dRect函数的功能

8、使用VC6.0实现窗口的任意分割

9、CSplitterWnd

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值