最近想做一个视窗分割的东西,在网上找了一些资料,终于“比葫芦 画瓢”地做了一个稍微看得过去的。现将过程记录上来以便以后查看,也让大家分享。主要参考了http://www.czvc.com/view.asp?id=334,这是一个相当不错的网站,本文并非完全照搬,对编译过程中存在的错误进行了改正,也对自己之前看到的其他资料以及上文中存在的问题进行了重点说明,这也是我在初学过程中易犯的错误。
界面内共含有一个框架和五个视窗,视窗Left、视窗 Right、视窗Zoom、视窗Control和视窗 Info。视窗Left、 Right和 Zoom的基类都是CView;视窗Control和视窗Info窗都从CFormView派生出来。
为了实现上述功能,首先用AppWizard生成一单文档应用程序,并自定义生成的默认视类为CZoomView 接下来,通过如下步骤,创建另外四个视窗:
1、用ClassWizard为应用程序创建一个新类CFixedSplitter,基类为CMDIChildWnd,然后在该类中将所有 CMDIChildWnd的地方替换为CsplitterWnd(因为ClassWizard不支持直接从CsplitterWnd类派生子类);
由CMDIChildWnd派生的新类CFixedSplitter里边的构造函数和析构函数都是保护成员,应在头文件中改为public,否则在CMainFrame构造时要出错。
2、在CMainFrame类里声明分割视图的变量:
CFixedSplitter SplitterH1; file://水平分割视窗1 CFixedSplitter SplitterH2; file://水平分割视窗2 CFixedSplitter SplitterV; file://垂直分割视窗
3、用ClassWizard为应用程序添加四个新类,其中CLeftView和CrightView从Cview类派生,CControlView和 CinfoView从CFormView类中派生;用资源管理器为两个CFormView类指定相应的对话框资源;注意这里一定要通过交互操作将两对话框的风格(属性)设置为WS_CHILD=On,WS_BORDER=Off,WS_VISIBLE=Off,WS_CAPTION=Off,即无标题、无边框、不可见的子窗口,如果这项工作没有作,编译时虽然能够通过,但运行时将会出现断言ASSERT错误;
4、在CMainFrame类的OnCreateClient函数中添加代码,创建分割视图
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { // TODO: Add your specialized code here and/or call the base class BOOL rtn=SplitterV.CreateStatic(this,1,2); //首先将窗口客户区分割为一行两列; //将左客户区再分割为三行一列,并以上面分割的左视窗作为父窗口; SplitterH1.CreateStatic(&SplitterV, 3, 1, WS_CHILD | WS_VISIBLE | WS_BORDER, SplitterV.IdFromRowCol(0,0)); //将右客户区再分割为两行一列,并以上面分割的右视窗作为父窗口; SplitterH2.CreateStatic(&SplitterV, 2, 1, WS_CHILD | WS_VISIBLE | WS_BORDER, SplitterV.IdFromRowCol(0,1)); //创建各自视图,并调用RUNTIME_CLASS运行库指定各视图的管理类 SplitterH1.CreateView(0, 0, RUNTIME_CLASS(CLeftView), CSize(0, 0), pContext); SplitterH1.CreateView(1, 0, RUNTIME_CLASS(CRightView), CSize(0, 0), pContext); SplitterH1.CreateView(2, 0, RUNTIME_CLASS(CControlView), CSize(0,0), pContext); SplitterH2.CreateView(0, 0, RUNTIME_CLASS(CZOOMView), CSize(0, 0), pContext); //在ZOOMView.h中要加上#include "ZOOMDoc.h",否则会出现一个找不到CZOOMDoc*的错误 SplitterH2.CreateView(1, 0, RUNTIME_CLASS(CInfoView), CSize(0, 0), pContext); //设置水平和垂直分割条的初始位置 SplitterV.SetColumnInfo(0,300,0); SplitterH1.SetRowInfo(0,150,0); SplitterH1.SetRowInfo(1,150,0); SplitterH2.SetRowInfo(0,200,0); return rtn; }
这样编译运行后,程序的界面基本上就有了模样。但是当鼠标移动到分割条位置始,鼠标的形状将会发生变化,呈现出拖动状态的图标,当按下鼠标左键并进行拖动操作时,分割条的位置将随鼠标的移动发生变化。如果程序需要禁止分割条的移动操作,那么还需要继续以下操作:
在CfixedSplitteWnd类中重载以下函数,以禁止鼠标拖动和光标变化:
void CFixedSplitterWnd::OnLButtonDown(UINT nFlags, CPoint point) { CWnd::OnLButtonDown(nFlags, point); //最后修改成CWnd的函数 } BOOL CFixedSplitterWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { return CWnd::OnSetCursor(pWnd, nHitTest, message); } void CFixedSplitterWnd::OnMouseMove(UINT nFlags, CPoint point) { CWnd::OnMouseMove(nFlags, point); }
接下来就可以象在多文档重叠窗口一样,管理自己的各自视图,每个视图可以分别显示各自的文档内容,非常方便。 本程序在WindowsXP下Visual C++6.0环境中调试通