静态分割窗口与多视图实例

来源:互联网 发布:php源码分析工具 编辑:程序博客网 时间:2024/06/04 18:28

转自:http://blog.csdn.net/u011478505/article/details/11620145

静态分割窗口与多视图实例

 

所谓多视,是指在同一个框架窗口下同时显示多个视图。通过运用这种技术,可以在框架的有限的空间内同时提供给用户更大的信息量,并且使得用户界面更加的友好,增强了软件的可操作性。

  窗口分割的基本概念

按照分割的时机的不同,窗口分割可以分为两类:动态分割和静态分割。

    动态分割是指用户可以动态的分割和合并窗口。动态分割最多可以有2行2列个窗口,并且所有的窗格只能使用同一种视图类。

    静态分割是指窗口在创建时,分割窗格窗口的窗格已经创建好了,且窗格的数量和顺序不会改变了,窗格为一个分隔条所分割,用户可以拖动分割条调整相应的窗格的大小。静态分割窗口最多可以有16行16列的窗格,但是各个窗格可以使用不同的视图类。

无论创建那一种分割,都必须在创建时指定最大的行数和列数,这些值是有CSplitterWnd对象进行管理。对于静态分割,必须创建指定数目的所有窗格以填满行和列。而对于动态分割,第一个窗格将在框架创建CSplitterWnd对象时自动创建。

窗口分割支持类CSplitterWnd

   CSplitterWnd类主要为窗口的风格提供了封装,窗口被分厂各个窗格后,又该类的对象负责管理。对于windows而言,CSplitterWnd

是一个真正的窗口,它完全占据了框架窗口的用户区域,而视图则占据了分割窗口的床片区域。CSplitterWnd窗口不参与命令传递机制。

使用时,CSplitterWnd对象通常为其父框架窗口CFrameWnd或CMDIChildWnd(MID应用中)对象的内嵌成员。CSplitterWnd对象创建过程如下。

在父框架窗口中嵌入CSplitterWnd类的对象成员;

重载父框架窗口的CFrameWnd::OnCreateClient成员函数;

从上一步重载的函数内部调用Create创建动态分割窗口或者调用CreateStatic创建静态的分割窗口。

下面介绍CsplitterWnd类的几个常用的函数

创建动态分割窗口函数Create

该函数用于动态创建分割窗口,同时将该窗口与类CSplitterWnd相关联,其生声明如下:

BOOL Create(CWnd*pParentWnd,  int nMaxRows,  int MaxCol, SIZE sizeMin,  CcreateContext* pContext,  DOWRD dwStyle = WS_CHILD | WS_VISIBLE | WS_HSCROLL| WSVSCROLL | SPLS_DYNAMIC_SPLIT,  UINT nID=AFX_IDW_PANE_FIRST);

各主要参数的含义如下:

pParentWnd:分割窗口的父框架窗口的指针

nMaxRows和你MaxCols:行与列的最大值,二者均不大于二

sizeMin:指定窗格被显示时的最小值。例如拖动分割框的幅度小于相应的值时,窗格将不会显示,但是可以调用该类的另外两个成员对此值进行改变。

 BOOL CMainFrame::onCreateClient(LPCREATESTRUCT lpcs,CcreateConText*pContext)

{

return m_wndSplitter.Create(this ,2,2,   /*设置行与列的数目*/Csize(10,10), /*窗格显示时最小值*/  pContext);

}

创建静态分割窗口函数CreateStatic

  该函数用于创建静态分割窗口,同时将该窗口与类CSplitterWnd相关联,其声明如下:

BOOL  CreateStatic(CWnd*  pParentWnd,  int  nRows,int  nCols, DWORD  dwStyle=WS_CHILD|WSVISBLE,UINTnID=AFX_IDW_PANE_FIRST);

主要参数的含义如下:

pParentWnd:分割窗口的父框架窗口指针

nRows和nCols:行与列的最大值,二者均不大于16

dwStyle:窗口风格,默认为子窗口可见,如果添加滚动条,则需另外设置WS_HSCROLL和WS_VSCROLL。

创建窗格视图函数CreateView

 CreateView函数为静态分割窗口创建窗格视图,在框架显示分割窗口之前,静态分割窗口的所有窗格都必须创建完毕。其声明如下:

Virtual  BOOL CreateView(int  row,intcol,CRuntimeClass* pViewClass,SIZE sizeInit, CcreateConText *pContext);

各个主要参数的含义如下:

row :分割窗口中新建视图所在的行。

col:分割窗口中新建视图所在的列。

pViewClass:新建视图的CRuntimeClass的指针。

sizeInit:新建视图的初始化大小。

创建静态分割窗口,并指定各窗格的视图的典型代码如下:

BOOLCMainFrame::OnCreateClient(LPCREATESTRUCT  lpcs,CcreateConText* pContext)

{

 BOOLbCreateSpltr=m_wndSplitter.CreateStatic(this,2,1);//静态分割

m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(COneView),CSize(0,0),pContext);

m_wndSplitter.CreateView(1,0,RUNTIME_CLASS(CAnotherView),CSize(0,0),pContext);

return (bCreateSpltr);

}

另外,CSplitterWnd还提供了一些用于获取和设置窗格属性的函数,常用的函数及其功能如下表。

CSplitterWnd类中的其他常用函数及实现的功能

成员函数

函数说明

GetColumnCount

获取窗口分割的窗格的列数

GetRowCount

获取窗口分割的窗格的行数

SetRowInfo

为窗格行设置最小宽和理想宽,行的最小值决定了行何时因为太小而不能显示

SetColnuInfo

为窗格列设置最小高和理想好,列的最小值决定了列何时因为太小而不能显示

OnDrawSplitter

此函数有框架负责调用,主要用来绘制或者指定分割窗口的确切特性

OnInvertTracker

使用设置分割条的属性,该函数在调整窗格大小期间有框架负责调用

 

静态分割与多视图实例

实例说明

 实例为一个基于单文档的MFc应用程序,通过静态分割窗口的方式三叉切分窗口,即共有三个窗格。程序实现的功能是用户可以输入学生的信息,并添加到列表视图中。程序最终运行的结果如下图:

程序运行结果


 

其中左侧的基本信息输入的窗格采用的是CFormView类型的视图,在用户可以其中进行信息的录入,单击“提交”按钮,数据就添加道文档中了,并在右侧的列表视图中显示。右侧信息显示的窗格采用的是CListView类型的视图,显示文档中存储的所有学生信息。而底部的窗格采用的是CEditView类型的视图,用于提示用户上一步添加的数据。下面介绍具体的实现过程。

 

创建工程

 

 使用AppWizard创建一个基于单文档的应用程序框架工程,工程名为“Guo”,其余的现象均采用默认设置。

添加视图类

需要为3个窗格添加3个视图类。CLeftFormView、CTopListView、CBottomEditView,其基类分别为CFormView、CListView和CEditView。

1、CLeftFormView类的实现

A、 添加对话框资源模板:添加CLeftFormView类之前,首先要向工程中添加CLeftFormView视图中对话框模板,如下图所示:

对话框模板的ID为“IDD_DIALOG1”,其Style属性设置为“Child”,Bolder属性设置为“None”。


B、添加CLeftFormView类。执行“Insert”→“New Class”菜单命令,弹出“New Class”对话框,在其中的Name编辑框中输入类名“CLeftFormView”,在Base Class列表框中选择基类“CFormView”选项,在Dialog ID列表框中选择“IDD_DIALOG1”对话框资源。单击Ok即可实现CLeftFormView类的添加。

C、添加CLeftFormView类的相关资源:利用Class Wizard在CLeftFormView中,为对话框模板的4个编辑控件分别添加CString类型的成员变量m_Num、m_Name、m_Magor、m_Home,并为“提交”按钮添加BN_CLICKED消息响应函数OnSubmit()。

2、CTopListView类的实现

  同样使用“New Class”对话框,添加CTopListView类,将其基类选择类型为CListView。然后使用Class Wizard重载该类的PreCreateWindow()函数,在其中定义列表视的类型,代码如下:

BOOLCTopListView::PreCreateWindow(CREATESTRUCT& cs)

{

    // TODO: Add your specialized code hereand/or call the base class

    cs.style=cs.style|LVS_REPORT;// 设置成报告列表的显示形式

 

    return CListView::PreCreateWindow(cs);

}

  使用Class Wizard重载CTopListView类的OnInitialUpdate()函数,在其中添加列表的表头,代码如下:

voidCTopListView::OnInitialUpdate()

{

    CListView::OnInitialUpdate();

    // TODO: Add your specialized code hereand/or call the base class

CStringm_ColumnLabelStr[]={"学号","姓名","专业","籍贯"};

 //表头字段

CListCtrl&   listctrl=GetListCtrl();//获取列表的控件

DWORD dwStyle =listctrl.GetExtendedStyle();

dwStyle|= LVS_EX_FULLROWSELECT;

// 选中某行使整行高亮(只适用与report风格的listctrl)

    dwStyle |= LVS_EX_GRIDLINES;      

    dwStyle |=LVS_EX_UNDERLINEHOT;

    listctrl.SetExtendedStyle(dwStyle);//列表风格

    int width[6]={80,80,110,150};

    for(int i=0;i<4;i++)

      {

listctrl.InsertColumn(i,m_ColumnLabelStr[i],LVCFMT_LEFT,width[i]);//设置表头

}

}

3、CBottomEidtView类的实现

同样使用New Class对话框,添加CBottomEditView类,将其基类选择为“CEditView”。而后使用Class Wizard重载该类的OnInitialUpdate()函数,在其中实现初始化设置,代码如下:

void CBottomEditView::OnInitialUpdate()

{

CEditView::OnInitialUpdate();

//TODO: Add your specialized code here and/or call the base class

 CEdit &mEdit=GetEditCtrl();    //获取编辑视图的控件

mEdit.SetWindowText("等待用户输入学生的信息!");//设置显示信息

mEdit.EnableWindow(FALSE);//编辑控件不可编辑

}

 

静态分割窗口的实现

窗口的分割过程中是首先在主框架CMainFrame中,将窗口分割成上下两个窗格,对应的视图分别为CGuoView和CBottomEditView。而后,再在CGuoView视图中将窗格分为左右两个窗格,对应的视图分别为CLeftFormView和CTopListView,实现过程如下。

1、 在CMainFrame类的头文件中,声明一个CSplitterWnd类的成员变量m_wndSplitter1,用于第一个窗口的分割

protected:  // control bar embedded members

        CStatusBar     m_wndStatusBar;

        CToolBar       m_wndToolBar;

      CSplitterWnd    m_wndSplitter1; //用于产生第一次的静态的分割

2、 使用Class Wizard重载CMainFrame类的OnCreateClient()函数,在其中实现第一次的窗口分割。

BOOLCMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)

{

  //TODO: Add your specialized code here and/or call the base class

   CRect rect;

   GetClientRect(&rect);  //产生第一次静态分割

   m_wndSplitter1.CreateStatic(this,  //父窗口指针

                              2,1); //行数与列数

   m_wndSplitter1.CreateView(0,0,  //窗格的行列序数

                           RUNTIME_CLASS(CGuoView),//视图类

                           CSize(rect.Width(),rect.Height()-rect.Height()/5),pContext);//父窗口创建参数

m_wndSplitter1.CreateView(1,0,RUNTIME_CLASS(CBottomEditView),

                            CSize(rect.Width(),rect.Height()/5),pContext);

                               //不在调用基类的OncreateClient函数

    return true;

}

包含相应的头文件,在MainFrame.cpp文件的开始加入下列语句

#include "GuoView.h"

#include "BottomEditView.h"

3、 在视图窗口类CGuoView的头文件中声明一个CSplitterWnd类的成员变量m_wndSplitter2,用于第二次窗口分割。

protected:

     CSplitterWnd m_wndSplitter2; //用于第二次窗口的分割

4、 使用Class Wizard重载CGuoView类的OnCreateClient()和OnSize()函数,实现窗口第二次分割并设置窗格的大小。

int CGuoView::OnCreate(LPCREATESTRUCTlpCreateStruct)

{

  if(CView::OnCreate(lpCreateStruct) == -1)

     return-1;

 

  //TODO: Add your specialized creation code here

  CRectrect;

  GetClientRect(&rect);  //   获得窗口的创建信息指针

  CCreateContext*pContext=(CCreateContext *)lpCreateStruct->lpCreateParams;

  m_wndSplitter2.CreateStatic(this,1,2);//产生第二次的静态分割

    //为第一个窗格产生视图

  m_wndSplitter2.CreateView(0,0,//窗口的行列序数

                     RUNTIME_CLASS(CLeftFormView),//视图类

                   CSize(rect.Width()/4,rect.Height()),//

                   pContext);

  //为第二个窗格产生视图

  m_wndSplitter2.CreateView(0,1,RUNTIME_CLASS(CTopListView),CSize(1,1),pContext);

  return0;

}

void CGuoView::OnSize(UINT nType, intcx, int cy)

{

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

  //TODO: Add your message handler code here

  CRect  rect;

  GetClientRect(&rect);

  intx=rect.Width();

  inty=rect.Height();

  m_wndSplitter2.MoveWindow(-2,-2,x,y+3);

  m_wndSplitter2.SetColumnInfo(0,x/4,0);  //左边窗格位置

  m_wndSplitter2.SetColumnInfo(1,x-x/4,0);  //右边窗格位置

  m_wndSplitter2.RecalcLayout();

 

}

至此,窗口的分割完成,编译运行程序,就会发现三叉窗口已经实现。如果在编译连接程序的时候出现如下面的错误:

c:\documents and settings\chenqi\桌面\guo\guoview.h(23) :error C2143: syntax error : missing ';' before '*'

c:\documents and settings\chenqi\桌面\guo\guoview.h(23) :error C2501: 'CGuoDoc' : missing storage-class or type specifiers

c:\documents and settings\chenqi\桌面\guo\guoview.h(23) :error C2501: 'GetDocument' : missing storage-class or type specifiers

则可以在CGuoView类头文件的前面加上这么一句class CGuoDoc; 就没有问题了。

 

窗格视图与文档的交互

 窗口中分割的各窗格视图对应着同一文档对象CGuoDoc,每个CView派生类都已经继承了GetDocument()函数,因此只要在调用后进行类型的强制转换就可以获取文档的对象。如:CGuoDoc* pDoc=(CGuoDoc*)GetDocument();

 本实例在文档对象CGuoDoc中,通过数组类对象存储学生信息,当在CLeftFormView视图中,输入学生信息单击“提交”按钮时,就将输入信息写入文档中的数组对象,并重绘各视图。

1、在CGuoDoc类的头文件中声明数组对象和数据修改标记,如下:

 Public:

   CStringArray infoArray[4];

    bool add;

并在构造函数中将add的值初始化为FALSE。

2、在CLeftFormView类的按钮响应函数OnSubmit()中,添加代码实现控件数据的保存并更新所有视图。

 voidCLeftFormView::OnSubmit()

{

   //TODO: Add your control notification handler code here

   UpdateData(TRUE);//   获取对话框的控件数据

   if(m_Num.IsEmpty()||m_Name.IsEmpty())    //判断是否为空

   {   AfxMessageBox("学号和姓名不能为空!");return; }

 

   CGuoDoc*pDoc=(CGuoDoc*)GetDocument();//   获取文档

   pDoc->infoArray[0].InsertAt(0,m_Num);    //  输入数据插入数据

   pDoc->infoArray[1].InsertAt(0,m_Name);

   pDoc->infoArray[2].InsertAt(0,m_Magor);

   pDoc->infoArray[3].InsertAt(0,m_Home);

   pDoc->add=true;      //添加了数据

   pDoc->UpdateAllViews(NULL);  //更新所有视图

   m_Num=_T("");

   m_Name=_T("");

   m_Magor=_T("");

   m_Home=_T("");

   UpdateData(FALSE);  //各控件的内容清空

 

}

包含CGuoDoc类的头文件,在CLeftFormView.cpp文件开始加入下列语句:

#include "GuoDoc.h"

3、重载视图类CTopListView和CBottomEditView中OnUpdate()函数,实现视图更新。

void CTopListView::OnUpdate(CView*pSender, LPARAM lHint, CObject* pHint)

{

   //TODO: Add your specialized code here and/or call the base class

   CGuoDoc*pDoc=(CGuoDoc*)GetDocument(); //获取文档指针

   if(pDoc->add)         //添加了数据

   {

        CListCtrl& listctrl=GetListCtrl();//  获取列表的控件

        listctrl.DeleteAllItems();       //删除所有项

        for(inti=0;i<pDoc->infoArray[0].GetSize();i++) //列表框中插入数据

        {

        listctrl.InsertItem(i,pDoc->infoArray[0].GetAt(i));

        listctrl.SetItemText(i,1,pDoc->infoArray[1].GetAt(i));

         listctrl.SetItemText(i,2,pDoc->infoArray[2].GetAt(i));

        listctrl.SetItemText(i,3,pDoc->infoArray[3].GetAt(i));

        }

   }

}

 

void CBottomEditView::OnUpdate(CView*pSender, LPARAM lHint, CObject* pHint)

{

   //TODO: Add your specialized code here and/or call the base class

     CGuoDoc* pDoc=(CGuoDoc*)GetDocument();//  获取文档指针

    if(pDoc->add)  //  添加了数据

     {

          CString str;

          str="添加了学号为"+pDoc->infoArray[0].GetAt(0)+"的学生信息!";

          CEdit &mEdit=GetEditCtrl();   //获取编辑视图控件

          mEdit.SetWindowText(str);  //显示信息

     }

}

同样需要在这两个视图类的资源文件中包含文档对象的头文件,如下:

#include "GuoDoc.h"

至此,实例开发结束,编译运行工程,即可实现要求的结果。

0 0
原创粉丝点击