基于MFC SDI的框架建立与视图分割

基于MFC SDI的框架建立与视图分割

本片笔记记录建立SDI的MFC程序,并简单归纳一下框架,视图,对话框,文档等之间的关系。

一、建立一个SDI的MFC程序。

在建立MFC程序时,有三个选项:基于多文档(MDI),基于单文档(SDI)以及基于对话框。其实他们之间有着很紧密的联系,甚至可以互相转换。这里就SDI的建立归纳如下:

1.新建一个MFC程序,在下面的界面中选择单个文档、MFC标准,windows本机默认。这样新建的程序才简洁,不然删起来也怪麻烦的。


2.本着以上原则,这里去掉系统菜单,去掉状态栏,也可以直接选使用经典菜单,但是我们这里为了后续实现窗口停靠和浮动功能,可以选择使用菜单栏和工具栏。

3.简洁得像个添加了Menu的对话框,只不过是白底的哈。可能是向导中的设置使得没了右上角的按钮,关闭多不方便。怎么办呢?去MainFrame里找到PreCreateWindow函数,把里面的Style注释掉就可以了。有时间真的得研究下这些宏定义的Style都是啥意思。

5.在介绍程序框架之前,首先对框架(Frame),视图(View),文档(Doc)进行下分析归纳。前方高能预警!

我们可以看到建立的工程里生成了Doc类、View类和MainFrame类,它们就分别是文档类、视图类和框架窗口类。

文档/视图结构是MFC提供的一种不错的设计,它将数据的处理和显示分开来,这样更便于我们对程序的维护和扩展。

文档:文档对象用于管理和维护数据,包括保存数据、取出数据以及修改数据等操作,在数据被修改以后,文档可以通知其对应的所有视图更新显示。

视图:视图对象将文档中的数据可视化,负责从文档对象中取出数据显示给用户,并接受用户的输入和编辑,将数据的改变反映给文档对象。视图充当了文档和用户之间媒介的角色。

框架:一个文档可能有多个视图界面,这就需要有框架来管理了。框架就是用来管理文档和视图的。框架窗口是应用程序的主窗口,应用程序执行时会先创建一个最顶层的框架窗口。视图窗口是没有菜单和边界的子窗口,它必须包含在框架窗口中,即置于框架窗口的客户区内。

文档和视图是一对多的关系。一个文档可以对应多个视图,例如在Word中一个文档有普通视图、大纲视图、Web版式视图、阅读版式视图等多种视图。而一个视图只能属于一个文档。最简单的应用程序是单文档单视图程序,除此之外还有单文档多视图程序、多文档程序等。

     6.有必要分析一下SDI的工程框架了。XXX.cpp文件是主线程的接口,包括 各种初始化和窗口的显示。注册应用程序的文档模板,文档模板。实现文档、框架窗口和视图之间的连接。XXXDoc.cpp对应文档,反正我从头到尾没改过这个文件。XXX.View则对应视图,完全可以在这里创建控件,但是好像很少有人这么干,因为光是一个视图,我就会去建立一个基于Dialog的MFC了。既然要有多个视图,就会用到后面介绍的视图分割,那么就需要新建view类了。MainFrame对应框架,里面可以写代码,实现重载接口,比如OnCreate和OnSize。(那个OutputWnd是个浮动窗口的类,后面再介绍)。

二、视图分割

 就是将一个窗口分割成多个窗格,在每个窗格中都包含有视图。MFC中的分割窗口类-CSplitterWnd类提供了分割窗口的功能。

MFC分割窗口的方式有两种,动态分割和静态分割。

动态分割窗口通常用于创建同一个文档对应的多个视图,而且这些视图一般都是同一类型的视图,能够在用户编辑文档的不同部分时提供方便。动态分割窗口最多可以有两行两列。对应的函数是:

m_wndSplit.Create(this,2, 2, CSize(10, 10), pContext);

静态分割窗口比较常见。我们经常能看到某个软件打开后,界面窗口默认被分割成了几个窗格,这就是静态分割窗口。静态分割窗口最多支持16行16列。通常静态分割窗口的每个窗格中包含不同类的视图,当然也可以是同一类的视图。对应的函数是:

m_wndSplit.CreateStatic(this,1,2);

1.MainFrm.h文件中为CMainFrame类添加成员对象:CSplitterWnd m_wndSplitter;

2.不论哪种分割都要在MainFrame.h中添加一个函数OnCreateClient,在这个函数下面实现。

virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs,CCreateContext* pContext);

3.如果你是静态分割,在添加了这个函数之后你想看一下分割效果,恐怕会中断,大概是找不到什么句柄。就这么个问题会让一个初学者半天摸不着头脑。其实深入理解就可以发现问题,因为静态分割时的显示的类是用户自定义的View,也就是说不能光分割,还必须给分割后的各个模块添加View。比如:

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

{

    //分割成两行两列

    if (!m_wndSplit.CreateStatic(this,2,2))

    {

       return FALSE;

    }

    CRect rect

    GetClientRect(&rect); //得得到当前窗口的尺寸,以便设置View大小

   

    //添加View,设置每个View的尺寸,注意不是分割窗口的尺寸,所以可能出现滚动条

if(!m_wndSplit.CreateView(0,0,RUNTIME_CLASS(CView1),CSize(rect.Width()/4,rect.Height()/4),pContext)||

    !m_wndSplit.CreateView(0,1,RUNTIME_CLASS(CView2),CSize(rect.Width()/4,rect.Height()/4),pContext)||

    !m_wndSplit.CreateView(1,0,RUNTIME_CLASS(CView3),CSize(rect.Width()/4,rect.Height()/4),pContext)||

    !m_wndSplit.CreateView(1,1,RUNTIME_CLASS(CView4),CSize(rect.Width()/4,rect.Height()/4),pContext))

    {

       m_wndSplit.DestroyWindow();

       return FALSE;

    }

   

    return TRUE;

}

    4.接下来你可以在这些View上添加控件了,甚至还可以添加一个Dialog。为了美观,设置均分窗口,且没有滚动条,且可以等比例缩放。原理就是在MainFrame里添加ON_WM_SIZE消息,并编写OnSize函数。千万注意这个判断很重要,感觉MFC创建窗口需要一定时间,而on_wm_size的响应还是很快的,会导致获得不到窗口句柄而中断。

void CMainFrame::OnSize(UINT nType, int cx, int cy)

{

    CFrameWndEx::OnSize(nType, cx, cy);

   

   

    if ((m_FirstShow&&IsWindowVisible()&&GetWindow(GW_CHILD))!=NULL)

       {

           CRect rect; 

           GetClientRect(&rect);

           m_wndSplit.SetRowInfo(0,rect.Height()/2,0);//设置横着的分割线(第1条)

           m_wndSplit.SetColumnInfo(0,rect.Width()/2,0);//设置竖着的分割线(第1条)         m_wndSplit.RecalcLayout();

           m_FirstShow = false;

       }

    else if (!m_FirstShow)

    {

       CRect rect; 

       GetClientRect(&rect);

       m_wndSplit.SetRowInfo(0,rect.Height()/2,0);

       m_wndSplit.SetColumnInfo(0,rect.Width()/2,0);

       m_wndSplit.RecalcLayout();

    }

}

5.可以在菜单栏里添加个选项,只要把它的ID定义为ID_WINDOW_SPLIT,就可以响应分割窗口了,看看效果把:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bjtuwayne

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值