关闭

用CSplitterWnd类分割窗体

442人阅读 评论(0) 收藏 举报
分类:

VC++6.0使用CSplitterWnd类分割窗体,拆分窗体

晚上一个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:
CMySplitter wndSplitter_horizontal;//水平分隔条
CMySplitter wndSplitter_erect;//竖直分隔条

第四步:打开资源视图,新建一个对话框,填写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) 
{
// TODO: Add your specialized code here and/or call the base class

//创建一个静态分栏窗口,分为2行1列 
if(wndSplitter_horizontal.CreateStatic(this,2,1)==NULL) 
return FALSE;

   //将CMonitorTopView视图连接到0行0列窗格上
   wndSplitter_horizontal.CreateView(0,0,RUNTIME_CLASS(CMonitorTopView),CSize(50,50),pContext);
   
  
    //将第1行0列再分开1行2列
    if(wndSplitter_erect.CreateStatic(&wndSplitter_horizontal,1,2,WS_CHILD|WS_VISIBLE, wndSplitter_horizontal.IdFromRowCol(1, 0))==NULL)
    
    return FALSE; 
   
     //将CMonitorView类连接到第二个分栏对象的0行0列
     wndSplitter_erect.CreateView(0,0,RUNTIME_CLASS(CMonitorView),CSize(220,220),pContext);
     
     //将CMonitorRightView类连接到第二个分栏对象的0行1列
     wndSplitter_erect.CreateView(0,1,RUNTIME_CLASS(CMonitorRightView),CSize(220,220),pContext); 
    
      return TRUE;


//return CFrameWnd::OnCreateClient(lpcs, pContext);
}

第六步:其实,截止到第五步完,我们运行程序就可以出现我图例所实现的样子了,但是现在我们来补充一下改变分隔条的特征,好了,现在你应该知道为什么我们要自己定义一个类,继承自CSplitterWnd了吧,因为我们要修改它的特征,例如改变分隔条的宽度,改变分隔条的颜色,固定分隔条(不让别人拖动)等等。

1、改变分隔条的宽度:在CMySplitter类的构造函数中加入代码,具体如下:

CMySplitter::CMySplitter()
{
m_cxSplitter = 10;    //must >=4 ,拖动时横向拖动条的宽度
m_cySplitter = 25;     //must >=4 ,拖动时竖向拖动条的宽度
m_cxBorderShare = 0; //按下鼠标时横向拖动条的偏移量
m_cyBorderShare = 0; //按下鼠标时竖向拖动条的偏移量
m_cxSplitterGap= 5; //静止时横向拖动条的宽度   
m_cySplitterGap= 5; //静止时横向拖动条的宽度

}

2、固定分隔条(不让别人拖动):锁定切分条的最简单的方法莫过于不让CSplitterWnd类来处理WM_LBUTTONDOWN,WM_MOUSEMOVE,WM_SETCURSOR消息,而是将这些消息交给CWnd窗口进行处理,从而屏蔽掉这些消息。现在我们打开CMySplitter类的头文件,我们手动的添加一些东西(为什么要手动呢?因为,我们选择的是Generic Class),好了,我们来看一下都加入了哪些代码:

class CMySplitter : public CSplitterWnd 
{
public:
CMySplitter();
virtual ~CMySplitter();

//以固定分隔条加入的代码

DECLARE_DYNCREATE(CMySplitter)
  
protected:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);


DECLARE_MESSAGE_MAP()

//以上是固定分隔条加入的代码
};

我们仔细的看一下在DECLARE_DYNCREATE(CMySplitter)和DECLARE_MESSAGE_MAP()之间是消息处理的声明,告诉计算机,我们重载了这三个消息处理函数。现在我们在打开CMySplitter类的.cpp文件,在构造函数CMySplitter::CMySplitter()上面加入如下代码:

IMPLEMENT_DYNCREATE(CMySplitter, CSplitterWnd)

BEGIN_MESSAGE_MAP(CMySplitter, CSplitterWnd)
ON_WM_LBUTTONDOWN()
ON_WM_SETCURSOR()
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()

在程序结尾添加下面的代码:

void CMySplitter::OnLButtonDown(UINT nFlags, CPoint point)
{     
    // 直接返回,不处理
return;
}

BOOL CMySplitter::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{   
    // 当光标进入分割窗口时,不允许改变样子,不处理
return FALSE;
}

void CMySplitter::OnMouseMove(UINT nFlags, CPoint point)
{       

     //将CSplitter类的处理改为由CWnd处理
      //CSplitterWnd::OnMouseMove(nFlags, point); 
    CWnd::OnMouseMove(nFlags, point);
}

好了,这样我们就实现了分隔条的固定。这一步是比较有难度的,因为我们要自己写一些消息处理代码。

最后我想大家都会发现一个问题,那就是,你运行出来的单文档程序的三个分割窗口上会出现滚动条,其原因是因为CFormView所基于的对话框模板比分割窗口要大,所以,会出现滚动条,那么我们适当的调整资源中的对话框模板的大小,使之比分割窗口小一点点,这时要注意,如果太小的话,整个单文档框架会缩小,切忌切忌,只要调整使之小一点点即可。

总结一下,分割窗体的重点在于要分析清楚分割顺序,各个子视图的位置。分割窗体,复杂但不难。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:20430次
    • 积分:306
    • 等级:
    • 排名:千里之外
    • 原创:7篇
    • 转载:19篇
    • 译文:0篇
    • 评论:3条
    文章分类
    最新评论