标签:mfc 窗体分割 csplitterwnd
1 引言行的结果如下图:
其中左侧的基本信息输入的窗格采用的是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: Add your specialized code here and/or call the base class
cs.style=cs.style|LVS_REPORT;// 设置成报告列表的显示形式
return CListView::PreCreateWindow(cs);
}
使用Class Wizard 重载CTopListView 类的OnInitialUpdate()函数,在其中添加列表的表头,
代码如下:
void CTopListView::OnInitialUpdate()
{
CListView::OnInitialUpdate();
// TODO: Add your specialized code here and/or call the base class
CString m_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()函数,在其中实现第一次的
窗口分割。
BOOL CMainFrame::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(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
CRect rect;
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);
return 0;
}
void CGuoView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
CRect rect;
GetClientRect(&rect);
int x=rect.Width();
int y=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()中,添加代码实现控件数据的保
存并更新所有视图。
void CLeftFormView::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(int i=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"
至此,实例开发结束,编译运行工程,即可实现要求的结果。
注意:编译可能会报:
error C2143: 语法错误 : 缺少“;”(在“*”的前面)
error C2501: “CTestView::CTestDoc” : 缺少存储类或类型说明符
error C2501: “CTestView::GetDocument” : 缺少存储类或类型说明符
warning C4183: “GetDocument”:缺少返回类型;假定为返回“int”的成员函数
解决方法:
C***View.h文件头添加
#include "C***Doc.h"
同时可以把C**View.cpp中上面去掉,
MFC的窗口分割的设计与实现以及CSplitterWnd 类分析,布布扣,bubuko.com
MFC的窗口分割的设计与实现以及CSplitterWnd 类分析
标签:mfc 窗体分割 csplitterwnd
原文地址:http://blog.csdn.net/luguifang2011/article/details/38146047