MFC的窗口分割的设计与实现以及CSplitterWnd 类分析

更新时间:2023-12-01 06:18:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

MFC的窗口分割的设计与实现以及CSplitterWnd 类分析

1 引言

在Microsoft VC++ 6.0 中,基于MFC 的应用程序一般分为以下几种:多文档界面(MDI)、单文档界面(SDI)以及基于对话框的应用程序。其中单文档又可分为单视图的和多视图的,一般情况下,单文档仅需要单视图就够了,如Windows 自带的记事本、画图程序等等,但在一些情况下,单文档需要多视图支持,比如同时观察文档的不同部分,同时从不同的角度观察同一文档等。在MFC 的框架下,文档对象(CDocument)有一个保存其所有视图的列表,并提供了增加视图(AddView)与删除视图(RemoveView)函数,以及当文档内容改变时通知其所有视图的方法(UpdateAllViews)。通过多文档框架的窗口复制机制和单文档框架的分割窗口机制是实现单文档多视图的主要方法。

2 单文档的多视图

一般地,单文档与多视图有三种情况:

(1)在多文档界面MDI 中,每个视图位于MDI 的一个独立子文档框架中,视图对象基于同一个视图类。用户可以通过“窗口| 新窗口”菜单,为同一文档的视图再创建一个窗口,通过新创建的窗口,可以编辑和观察文档的另一部分,同一文档各个视图之间自动实现同步,用户修改一个视图的内容,在另外的视图中也自动更新。MFC 框架通过复制原来的子框架窗口和其中的视图来实现上面的功能,并且是完全自动的。

(2)视图对象基于同一视图类,所有视图位于同一文档框架中。分割窗口将单文档窗口的视图区分割成几个独立的视图,框架从同一视图类创建多个视图对象。Word 的子窗口即属于这种类型。

(3)视图对象基于不同的视图类,所有的视图位于同一文档框架中。多个视图共享同一文档框架,但从不同的视图类创建,每个视图可以为文档提供不同的观察和编辑方法。比如在一个窗口里观察文档的不同部分,或者是在一个窗口里用不用类型的视图观察同一个文档。这种类型的实现方法是通过重载框架类CMainFrame 的成员函数OnCreateClient 实现,用户可以根据不同需要将窗口分为垂直或水平的多个分割窗口。

下面通过实例设计,介绍单文档多视图的窗口分割和多视图之间的通信的实现方法。

实例为一个基于单文档的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()函数,在其中定义列表视的类型,代码如下:

BOOL CTopListView::PreCreateWindow(CREATESTRUCT& cs) { }

// TODO: 在此添加专用代码和/或调用基类

cs.style = cs.style | LVS_REPORT;// 设置成报告列表的显示形式 return CListView::PreCreateWindow(cs);

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

void CTopListView::OnInitialUpdate() { 头 }

}

// TODO: 在此添加专用代码和/或调用基类

CString m_ColumnLabelStr[] = { L\学号\, L\姓名\, L\专业\, L\籍贯\ }; //表头字段

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]); // 设置表CListView::OnInitialUpdate();

3、CBottomEidtView 类的实现

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

void CBottomEditView::OnInitialUpdate() { }

// TODO: 在此添加专用代码和/或调用基类

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

mEdit.SetWindowText(L\等待用户输入学生的信息!\);//设置显示信息 mEdit.EnableWindow(FALSE); //编辑控件不可编辑 CEditView::OnInitialUpdate();

静态分割窗口的实现

窗口的分割过程中是首先在主框架 CMainFrame 中,将窗口分割成上下两个窗格,对应的视图分别为CGuoView 和CBottomEditView。而后,再在CGuoView 视图中将窗格分为左右两个窗格,对应的视图分别为CLeftFormView 和CTopListView,实现过程如下。 1、在 CMainFrame 类的头文件中,声明一个CSplitterWnd 类的成员变量m_Splitterwnd1,

用于第一个窗口的分割

protected: // 控件条嵌入成员

CMFCMenuBar m_wndMenuBar; CMFCToolBar m_wndToolBar; CMFCStatusBar m_wndStatusBar; ......

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

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

窗口分割。

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { }

// TODO: 在此添加专用代码和/或调用基类 CRect rect;

GetClientRect(&rect); //产生第一次静态分割 m_Splitterwnd1.CreateStatic(this, //父窗口指针

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

RUNTIME_CLASS(CGuoView),//视图类

CSize(rect.Width(), rect.Height() - rect.Height() / 5), pContext);//父窗口创建m_Splitterwnd1.CreateView(0, 0, //窗格的行列序数

参数

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

CSize(rect.Width(), rect.Height() / 5), pContext); //不在调用基类的OncreateClient 函数 return true;

//return CFrameWndEx::OnCreateClient(lpcs, pContext);

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

#include \

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

protected:

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

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

int CGuoView::OnCreate(LPCREATESTRUCT lpCreateStruct) {

// TODO: 在此添加您专用的创建代码 CRect rect;

GetClientRect(&rect);

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

return -1;

本文来源:https://www.bwwdw.com/article/s2ft.html

Top