晚上一个QQ技术群中的人提出了一个比较尖锐的问题,其尖锐性并不是在于难度,而是复杂度,分割窗体,也叫拆分窗体,这个问题还是值得仔细去研究一番的,下面切入正题。因为比较复杂,所以这个问题我会讲的很细致,基本是带着做下来。 我们在使用WINDOWS的资源管理器的时候都会注意到,他是由左右两部分组成,这就是分割窗体,那么现在我们就来给大家讲一下如何拆分窗体,而且是想怎么拆就怎么拆。以上图的三分窗体为例。(三分会用了,多分就会了)。 多说一句,为了更加直观的体现出分割窗体,我所举的图例当中单文档的菜单栏和工具栏被去掉了,具体方法参见我的另一篇文章《[原创]VC++6.0去掉单文档中的菜单,工具栏,状态栏》。 首先,我们需要定义一个自己的类,继承于CSplitterWnd类,至于为什么不直接使用,而要自己定义,继承呢?现在我先不回答,到后面就清楚了。 第一步:打开Visual C++ 6.0,文件—>新建,选择MFC AppWizard(exe),输入工程名test,点确定,然后选择单文档点下一步,第二,第三,第四,第五都点下一步,第六步的时候让我选择每个类的基类,我们把CTestView类的基类改为CFormView,点完成。 第二步:新建一个类,类的类型选择Generic Class,填写名称为CMySplitter,基类我们填CSplitterWnd,点击确定。这个时候我们有可能会遇到一个问题(之所以我说有可能是因为这种情况有时不会发生),那就是当我们点击确定之后有时会弹出一个对话框,说找不到CSplitterWnd.h文件,这个时候我们点确定即可。因为,MFC的Classwizard不支持继承CSplitter类。但是,我们这里选择的是Generic Class,而不是MFC,所以可以继承,忽略掉那个提醒即可,不明白原因不要紧,只要记得如果弹出对话框,只要点确定即可。 第三步:在CMainFrame类的头文件最顶部加上#include "MySplitter.h",再在CMainFrame类中声明两个public的CMySplitter型的成员变量,如下: public: 第四步:打开资源视图,新建一个对话框,填写ID为IDD_MONITORTOP_FORM,新建一个类,类的类型选择MFC Class,填写名称为CMonitorTopView,基类我们填CFormView,对话框ID我们填写IDD_MONITORTOP_FORM,这样我们就新建了一个以CFormView为基类的视图类CMonitorTopView。类似的,我们再新建另外一个对话框,ID为IDD_MONITORRIGHT_FORM,以此再建立一个以CFormView为基类的视图类CMonitorRightView。 第五步:重载CMainFrame类的OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)方法。加入代码,具体如下: BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
第六步:其实,截止到第五步完,我们运行程序就可以出现我图例所实现的样子了,但是现在我们来补充一下改变分隔条的特征,好了,现在你应该知道为什么我们要自己定义一个类,继承自CSplitterWnd了吧,因为我们要修改它的特征,例如改变分隔条的宽度,改变分隔条的颜色,固定分隔条(不让别人拖动)等等。 1、改变分隔条的宽度:在CMySplitter类的构造函数中加入代码,具体如下: CMySplitter::CMySplitter() } 2、固定分隔条(不让别人拖动):锁定切分条的最简单的方法莫过于不让CSplitterWnd类来处理WM_LBUTTONDOWN,WM_MOUSEMOVE,WM_SETCURSOR消息,而是将这些消息交给CWnd窗口进行处理,从而屏蔽掉这些消息。现在我们打开CMySplitter类的头文件,我们手动的添加一些东西(为什么要手动呢?因为,我们选择的是Generic Class),好了,我们来看一下都加入了哪些代码: class CMySplitter : public CSplitterWnd //以固定分隔条加入的代码 DECLARE_DYNCREATE(CMySplitter) //以上是固定分隔条加入的代码 我们仔细的看一下在DECLARE_DYNCREATE(CMySplitter)和DECLARE_MESSAGE_MAP()之间是消息处理的声明,告诉计算机,我们重载了这三个消息处理函数。现在我们在打开CMySplitter类的.cpp文件,在构造函数CMySplitter::CMySplitter()上面加入如下代码: IMPLEMENT_DYNCREATE(CMySplitter, CSplitterWnd) BEGIN_MESSAGE_MAP(CMySplitter, CSplitterWnd)
在程序结尾添加下面的代码: void CMySplitter::OnLButtonDown(UINT nFlags, CPoint point) BOOL CMySplitter::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) void CMySplitter::OnMouseMove(UINT nFlags, CPoint point) //将CSplitter类的处理改为由CWnd处理 好了,这样我们就实现了分隔条的固定。这一步是比较有难度的,因为我们要自己写一些消息处理代码。
最后我想大家都会发现一个问题,那就是,你运行出来的单文档程序的三个分割窗口上会出现滚动条,其原因是因为CFormView所基于的对话框模板比分割窗口要大,所以,会出现滚动条,那么我们适当的调整资源中的对话框模板的大小,使之比分割窗口小一点点,这时要注意,如果太小的话,整个单文档框架会缩小,切忌切忌,只要调整使之小一点点即可。 总结一下,分割窗体的重点在于要分析清楚分割顺序,各个子视图的位置。分割窗体,复杂但不难。 |