博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
VS2010 MFC中 窗口分割的实现
阅读量:5237 次
发布时间:2019-06-14

本文共 7271 字,大约阅读时间需要 24 分钟。

分割窗口概述

       分割窗口,顾名思义,就是将一个窗口分割成多个窗格,在每个窗格中都包含有视图,或者是同一类型的视图,或者是不同类型的视图。

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

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

       大家看下Word里的动态分割窗口就很明白了,以Word 2007文档为例,在菜单中点击视图”->“拆分,就可以看到一条随鼠标移动的分隔条,当我们在文档中某个位置按下鼠标左键时,分割条就固定了下来,生成了上下两个分割窗格,通过滚动每个窗格中的垂直滚动条可以看到,两个窗格中的内容相同,这就是所说的对应同一个文档的同一类视图。

       动态分割窗口最多可以有两行两列。

       静态分割窗口比较常见。我们经常能看到某个软件打开后,界面窗口默认被分割成了几个窗格,这就是静态分割窗口。

       静态分割窗口指在窗口创建时,分割的窗格就已经生成了,而且用户不能改变窗格的数量和顺序。静态分割窗口最多支持1616列。通常静态分割窗口的每个窗格中包含不同类的视图,当然也可以是同一类的视图。

 

CSplitterWnd

 

       MFC中的分割窗口类-CSplitterWnd类提供了分割窗口的功能。CSplitterWnd类中包含一个分割器窗口,该分割器窗口就是一个包含多个窗格的窗口。我们分割窗口时就是直接在此分割器窗口中分割的。

下面是三个最常用的成员函数:

 

virtual BOOL Create(      CWnd* pParentWnd,      int nMaxRows,      int nMaxCols,      SIZE sizeMin,      CCreateContext* pContext,      DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | SPLS_DYNAMIC_SPLIT,      UINT nID = AFX_IDW_PANE_FIRST    );  

 

 

     创建动态分割窗口。参数pParentWnd为分割器窗口的父框架窗口;参数nMaxRows为分割器窗口的最大行数,不能超过2;参数nMaxCols为分割器窗口的最大列数,也不能超过2;参数sizeMin为窗格能显示的最小尺寸,如果窗格尺寸小于sizeMin则不显示;参数pContext为指向CCreateContext结构的指针,大多数情况下可以赋值为父框架窗口的pContext;参数dwStyle指定窗口风格;参数nID为分割窗口的ID,除非分割器窗口嵌入到另一个分割器窗口中,否则可以取值AFX_IDW_PANE_FIRST

 

 

virtual BOOL CreateStatic(      CWnd* pParentWnd,      int nRows,      int nCols,      DWORD dwStyle = WS_CHILD | WS_VISIBLE,      UINT nID = AFX_IDW_PANE_FIRST    );  

 

    创建静态分割窗口。参数pParentWnddwStylenID同上;参数nRows为行数,不能超过16;参数nCols为列数,同样不能超过16

 

 

virtual BOOL CreateView(      int row,      int col,      CRuntimeClass* pViewClass,      SIZE sizeInit,      CCreateContext* pContext    );  

 

     为静态分割窗口创建窗格视图。参数row指定分割器窗口中放置新视图的行;参数col指定放置新视图的列;参数pViewClass指定新视图的CRuntimeClass对象;参数sizeInit指定新视图的初始大小;参数pContext为指向CCreateContext结构的指针,通常可以赋值为传递给父框架窗口的重载函数CFrameWnd::OnCreateClientpContext参数值。

 

 

动态分割窗口

 

       创建动态分割窗口的一般步骤为:

 

       1. 在父框架类中定义一个CSplitterWnd类型的成员对象。

 

       2. 重载父框架类的CFrameWnd::OnCreateClient成员函数。

 

       3. 在重载的CFrameWnd::OnCreateClient函数中调用CSplitterWnd成员对象的Create函数。

 

实例:我们要实现在主框架窗口的客户区中创建两行两列的动态分割窗口。

     以下是创建动态分割窗口的具体步骤:

 

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

 

       2. Class View类视图中找到CMainFrame类,右键点击,在右键菜单中选择Properties,就会显示属性页,然后在属性页的工具栏上点击TipOverrides的按钮,下面的列表中就列出了能够重载的函数,找到OnCreateClient生成重载函数。

 

       3. MainFrm.cpp文件中找到刚重载的OnCreateClient函数修改如下:

 

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)   {    // TODO: Add your specialized code here and/or call the base class    // 创建动态分割窗口,两行两列    return m_wndSplitter.Create(this,2, 2, CSize(100, 100), pContext);      //return CFrameWndEx::OnCreateClient(lpcs, pContext);   }  

 

       4. Resource View资源视图中,打开Menu下的IDR_MAINFRAME菜单,在View下添加一个菜单项,Caption设为Splitter WindowID设为(一定要设为)ID_WINDOW_SPLIT。这样在运行结果界面中点击此菜单项时MFC会执行一些操作显示动态分割窗口。

       5. 运行程序,点击菜单中的View->Splitter Window菜单项,即可看到创建动态分割窗口后效果。

 

 

静态分割窗口

 

       创建静态分割窗口的一般步骤为:

 

       1. 在父框架类中定义一个CSplitterWnd类型的成员对象。

 

       2. 重载父框架类的CFrameWnd::OnCreateClient成员函数。

 

       3. 在重载的CFrameWnd::OnCreateClient函数中调用CSplitterWnd成员对象的CreateStatic成员函数,然后可以调用CSplitterWnd成员对象的CreateView成员函数为每个窗格创建视图。 

 

实例:在主框架窗口中的客户区创建一个两行一列的静态分割窗口。

      以下是创建静态分割窗口的具体步骤:

 

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

 

       2. Class View类视图中找到CMainFrame类,右键点击,在右键菜单中选择Properties,就会显示属性页,然后在属性页的工具栏上点击TipOverrides的按钮,下面的列表中就列出了能够重载的函数,找到OnCreateClient生成重载函数。

 

       3. MainFrm.cpp文件中找到刚重载的OnCreateClient函数进行修改。若没有新建其他视图类,则上下两个窗格的视图可以都用CExampleView。为了能识别CExampleView类,还需在MainFrm.cpp文件中添加#include "ExampleView.h",在ExampleView.h文件中添加#include "ExampleDoc.h"。最终OnCreateClient函数修改如下:

 

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)   {       // TODO: Add your specialized code here and/or call the base class       CRect rc;         // 获取框架窗口客户区的CRect对象       GetClientRect(&rc);         // 创建静态分割窗口,两行一列       if (!m_wndSplitter.CreateStatic(this, 2, 1))           return FALSE;         // 创建上面窗格中的视图       if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CExampleView), CSize(rc.Width(), rc.Height()/2), pContext))           return FALSE;         // 创建下面窗格中的视图       if (!m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(CExampleView), CSize(rc.Width(), rc.Height()/2), pContext))           return FALSE;         return TRUE;         //return CFrameWndEx::OnCreateClient(lpcs, pContext);   }  

 

      4. 运行程序,即可看到效果。

 

 

若想在其中某个窗格中再嵌套分割窗口,那么就需要再定义一个CSplitterWnd对象,以父窗格所在的CSplitterWnd对象为父框架窗口创建分割窗口即可。

 

实例:创建一个具有左上,左下和右边这三个视图的静态分割窗口。

      以下是创建静态分割窗口的具体步骤:

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

                              protected:

                                    CSplitterWnd m_wndSplitter;
                                    CSplitterWnd m_wndSplitter1;

       2. 在Class View类视图中找到CMainFrame类,右键点击,在右键菜单中选择Properties,就会显示属性页,然后在属性页的工具栏上点击Tip为Overrides的按钮,下面的列表中就列出了能够重载的函数,找到OnCreateClient生成重载函数。

       3. 在MainFrm.cpp文件中找到刚重载的OnCreateClient函数进行修改。这里可以先建好三个视图类:CMessageView,CInputView,CUserView

最终OnCreateClient函数修改如下:

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext){    // create splitter window    if (!m_wndSplitter.CreateStatic(this, 1, 2))        return FALSE;    if (!m_wndSplitter1.CreateStatic(        &m_wndSplitter,     // our parent window is the first splitter        2, 1,               // the new splitter is 2 rows, 1 column        WS_CHILD | WS_VISIBLE | WS_BORDER,  // style, WS_BORDER is needed        m_wndSplitter.IdFromRowCol(0, 0)            // new splitter is in the first row, 2nd column of first splitter       ))    {        TRACE0("Failed to create nested splitter\n");        return FALSE;    }    if(!m_wndSplitter1.CreateView(0,0, RUNTIME_CLASS(CMessageView), CSize(100,100), pContext))    {        m_wndSplitter.DestroyWindow();        m_wndSplitter1.DestroyWindow();        return FALSE;    }    if(!m_wndSplitter1.CreateView(1,0, RUNTIME_CLASS(CInputView), CSize(100,100), pContext))    {        m_wndSplitter.DestroyWindow();        m_wndSplitter1.DestroyWindow();        return FALSE;    }    if(!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CUserView), CSize(100, 100), pContext))    {        m_wndSplitter.DestroyWindow();        return FALSE;    }    m_wndSplitter.SetColumnInfo(0, 450,100);    m_wndSplitter1.SetRowInfo(0, 250, 100);    return TRUE;}

 4. 运行程序,即可看到效果如下:

 

若想创建具有左边,右上和右下这三个视图的静态分割窗口,即可修改OnCreateClient函数如下:

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext){    // TODO: 在此添加专用代码和/或调用基类    CRect rc;    // 获取框架窗口客户区的CRect对象    GetClientRect(&rc);    //创建拆分窗口,分割为两列     if (!m_wndSplitter.CreateStatic(this, 1, 2))        return FALSE;    //把窗口第2列再分割为两行    if (!m_wndSplitterRight.CreateStatic(&m_wndSplitter, 2, 1,WS_CHILD | WS_VISIBLE | WS_BORDER, m_wndSplitter.IdFromRowCol(0,1)))        return FALSE;    //创建视图    if(!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CUserView), CSize(rc.Width()/4 , rc.Height()), pContext))    {        m_wndSplitter.DestroyWindow();        return FALSE;    }    if(!m_wndSplitterRight.CreateView(0,0, RUNTIME_CLASS(CMessageView), CSize(rc.Width()*3/4, rc.Height()*4/5), pContext))    {        m_wndSplitter.DestroyWindow();        m_wndSplitterRight.DestroyWindow();        return FALSE;    }    if(!m_wndSplitterRight.CreateView(1,0, RUNTIME_CLASS(CInputView), CSize(rc.Width()*3/4, rc.Height()/5), pContext))    {        m_wndSplitter.DestroyWindow();        m_wndSplitterRight.DestroyWindow();        return FALSE;    }    return TRUE;}

 

最后一个左边,右上和右下三视图的实例花了不少功夫,一直报错,结果是 m_wndSplitterRight.CreateView(0,0,......) 这里的 0,0 没搞清楚。

整理于此,希望能给遇到同样问题的朋友一些帮助~~~~~

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/lxt287994374/p/3419380.html

你可能感兴趣的文章
js 时间对象方法
查看>>
网络请求返回HTTP状态码(404,400,500)
查看>>
Spring的JdbcTemplate、NamedParameterJdbcTemplate、SimpleJdbcTemplate
查看>>
Mac下使用crontab来实现定时任务
查看>>
303. Range Sum Query - Immutable
查看>>
图片加载失败显示默认图片占位符
查看>>
【★】浅谈计算机与随机数
查看>>
解决 sublime text3 运行python文件无法input的问题
查看>>
javascript面相对象编程,封装与继承
查看>>
Atlas命名空间Sys.Data下控件介绍——DataColumn,DataRow和DataTable
查看>>
Java中正则表达式的使用
查看>>
算法之搜索篇
查看>>
新的开始
查看>>
java Facade模式
查看>>
NYOJ 120校园网络(有向图的强连通分量)(Kosaraju算法)
查看>>
Leetcode 226: Invert Binary Tree
查看>>
http站点转https站点教程
查看>>
解决miner.start() 返回null
查看>>
bzoj 2007: [Noi2010]海拔【最小割+dijskstra】
查看>>
BZOJ 1001--[BeiJing2006]狼抓兔子(最短路&对偶图)
查看>>