对话框属性页(VC_MFC)
目录
属性页编写总体思路
CPropertySheet 编程
Tab Control 控件
(本章节中例子都是用 VS2005 编译调试的)
属性页编写总体思路
大体思想:
设置对话框属性页属性:
属性名 值
System Menu False
Style Child
Title Bar False
Border None
代码样例(这里我一几个按钮控件来演示):
添加两个对话框资源并为对话框资源定义相关属性,资源 ID 为IDD_PAGE1,IDD_PAGE2,资源视图如下所示:
为主对话框添加相关成员变量(属性页关联对象,CDialog 数组指针,当前显示标签页的索引)代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//记录当前显示页面的索引 int m_CurSelTab; //属性页对话框对象 CPage1 m_p1; CPage2 m_p2; //对话框数组 CDialog* pDialog[2];
在主对话框的 OnInitDialog 函数中初始化属性页相关操作,添加的具体代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//创建两个对话框,并将 CTabCtrl 对象作为其父窗口 m_p1.Create(IDD_PAGE1, this); m_p2.Create(IDD_PAGE2, this); //把对话框对象与 CDialog 数组联系起来 pDialog[0] = &m_p1; pDialog[1] = &m_p2; //获得 Tab Control 客户区矩形大小 CRect rc; GetClientRect(rc); //调整矩形大小让属性页显示在适当的位置上 rc.top += 2; rc.bottom -= 2; rc.left += 2; rc.right -= 200; //移动对话框窗口到矩形区域中 m_p1.MoveWindow(&rc); m_p2.MoveWindow(&rc); //显示初始页面,保存当前选择 pDialog[0]->ShowWindow(SW_SHOW); pDialog[1]->ShowWindow(SW_HIDE); m_CurSelTab = 0;
然后为对话框添加两个按钮并通过这个两个按钮的事件响应函数来实现属性页的切换,具体代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* 按钮一实现把属性页切换到第一个页面 *******************/ void CtestDlg::OnBnClickedButton1() { // TODO: 在此添加控件通知处理程序代码 //把当前的页面隐藏起来 pDialog[m_CurSelTab]->ShowWindow(SW_HIDE); //设置新的页面索引 m_CurSelTab = 0; //把新的页面显示出来 pDialog[m_CurSelTab]->ShowWindow(SW_SHOW); } /* 按钮二实现把属性页切换到第二个页面 *******************/ void CtestDlg::OnBnClickedButton2() { // TODO: 在此添加控件通知处理程序代码 //把当前的页面隐藏起来 pDialog[m_CurSelTab]->ShowWindow(SW_HIDE); //设置新的页面索引 m_CurSelTab = 1; //把新的页面显示出来 pDialog[m_CurSelTab]->ShowWindow(SW_SHOW); }
运行结果:
CPropertySheet 编程
对话框属性页资源
普通对话框资源和属性页资源对话框的区别:
选项 普通对话框 属性页对话框
Style Popup Child
Border Dialog Thin
System menu 选中 未选中
可以把普通对话框按照上面修改便可以称为属性页对话框
创建对话框属性页资源
编写CPropertySheet流程图:
代码样例:
属性页模式
创建两个属性页资源 ID 为 IDD_PAGE1 与 IDD_PAGE2,并关联两个 CPropertyPage 派生类,类分别为 CPage1,CPage2.资源视图如下:
CPage1 与 CPage2 源码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// 因为大致是一样的所以这里以 CPage1 文件为例子,不一样的地方我也列了出来 /* CPage1 CPage2 对话框头文件 ***************************/ class CPage1 : public CPropertyPage //class CPage2 : public CPropertyPage { DECLARE_DYNAMIC(CPage1) //DECLARE_DYNAMIC(CPage2) public: CPage1(); //CPage2(); virtual ~CPage1(); //virtual ~CPage2(); // 对话框数据 enum { IDD = IDD_PAGE1 }; //enum { IDD = IDD_PAGE2 }; protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 支持 DECLARE_MESSAGE_MAP() }; /* CPage1 CPage2 对话框实现文件 *************************/ IMPLEMENT_DYNAMIC(CPage1, CPropertyPage) //IMPLEMENT_DYNAMIC(CPage2, CPropertyPage) CPage1::CPage1() : CPropertyPage(CPage1::IDD) //CPage2::CPage2() // : CPropertyPage(CPage2::IDD) { } CPage1::~CPage1() //CPage2::~CPage2() { } void CPage1::DoDataExchange(CDataExchange* pDX) //void CPage2::DoDataExchange(CDataExchange* pDX) { CPropertyPage::DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CPage1, CPropertyPage) //BEGIN_MESSAGE_MAP(CPage2, CPropertyPage) END_MESSAGE_MAP()
在工程中添加一个派生于 CPropertySheet 类,这里我不它命名为 CMyProSh,然后在 CMyProSh 中添加 CPage1,CPage2 对象作为其成员变量,并在构造函数中用 AddPage 函数把 CPage1,CPage2 对象添加到属性表单中去.CMyProSh 程序源码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//MyProSh.h #pragma once #include "Page1.h" #include "Page2.h" class CMyProSh : public CPropertySheet { CPage1 m_p1; CPage2 m_p2; ... } //MyProSh.cpp CMyProSh::CMyProSh(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage) :CPropertySheet(nIDCaption, pParentWnd, iSelectPage) { this->AddPage(&m_p1); this->AddPage(&m_p2); } CMyProSh::CMyProSh(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage) :CPropertySheet(pszCaption, pParentWnd, iSelectPage) { this->AddPage(&m_p1); this->AddPage(&m_p2); }
在主对话框中添加一个按钮然后为按钮添加事件响应函数,在函数中添加如下代码:
//创建表单类对象 CMyProSh pro(L"表单样例"); //显示模态表单对话框 pro.DoModal();
运行结果:
向导模式:
相关函数:
- CPropertySheet::SetWizardButtons
- CPropertySheet::SetWizardMode
- CPropertyPage::OnWizardBack
- CPropertyPage::OnWizardFinish
- CPropertyPage::OnWizardNext
代码样例:
在创建模态对话框前的步骤与属性页模式一致.但在调用 DoModal 函数创建模态对话框前需要先调用 SetWizardMode 成员函数.代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//创建表单类对象 CMyProSh pro(L"表单样例"); //设置向导模式 pro.SetWizardMode(); //显示模态表单对话框 pro.DoModal();
运行结果:
Tab Control 控件
说明:
Tab Control 的运行效果有点像 Property Sheet,但两者还是有一些区别.我的理解就是Property Sheet主要用在对话框中,对数据进行进行分类管理.而 Tab Control 使用范围更广一些,既可以用在对话框,也可以用在视图中,除了可以管理配置数据外,还可以对软件的组织进行规划,比如可以通过它来切换不同的视图等等,当然这不是没有代价的,Tab Control 的编程就比 Property Sheet 的复杂很多.但是不是每个 Tab Control 的标签页对应一个页面
对于客户区其实只有一个,工作原理其实就是有许多的子对话框在客户区上但是只有一个显示而其他的都没有显示通过按标签页后相应事件让现在显示的子对话框隐藏而对应于标签页索引的某个子对话框显示
相关函数:
CTabCtrl 类成员函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
[插入项][获得标签页总数目][删除对应标签页][删除所有标签页][获得标签页矩形空间][获得当前标签页索引][设置某标签页为显示标签页]
函数原型:
LONG InsertItem( int nItem, LPCTSTR lpszItem );
参数说明:
- nItem: 为插入位置
- lpszItem: 为标签页标题内容
作用: 插入一个新的标签页在tab control控件里面的nItem位置处,若nItem位置大于控件中标签页的总数则表明在最后的位置添加一个新的标签页
函数原型:
int GetItemCount( ) const
返回值: 返回控件中标签页的总数
函数原型:
BOOL DeleteItem( int nItem);
参数说明: nItem 要删除的标签页的位置
作用: 删除一个在nItem位置处以存在的标签页,若nItem位置大于控件中标签页的总数,它将不执行任何操作
函数原型:
BOOL DeleteAllItems( );
作用: 删除控件中所有的标签页
函数原型:
BOOL GetItemRect( int nItem, LPRECT lpRect ) const;
参数说明:
- nItem: 要获取矩形空间的标签位置
- lpRect: 用于接收标签的矩形空间
作用: 用 lpRect 来接收位置为 nItem 的标签页面上索引页面的小矩形,而不是控件的客户区
函数原型:
int GetCurSel( ) const;
返回值: 返回标签页的索引
函数原型:
int SetCurSel( int nItem );
参数说明: nItem 要设置为当前标签页的索引位置
作用: 用在nItem位置的标签页来作为当前显示的标签页
CWnd 类成员函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
函数原型:
void GetClientRect(LPRECT lpRect ) const;
参数说明: lpRect 用于记录客户区矩形空间
说明: 获得窗体的客服区的矩形记入在 lpRect 中
函数原型:
void MoveWindow(int x,int y,int nWidth,int nHeight,BOOL bRepaint = TRUE ); void MoveWindow(LPCRECT lpRect,BOOL bRepaint = TRUE );
参数说明:
- x: 移动到的区间的左上角横坐标
- y: 移动到的区间的左上角纵坐标
- nWidth: 移动到的区间的宽度
- nHeight: 移动到的区间的高度
- bRepaint: 是否发生窗口重绘
- lpRect: 移动到的矩形区间
说明: 改变窗体类的位置和大小
BOOL ShowWindow( int nCmdShow );
参数取值:
- SW_HIDE
- SW_MINIMIZE
- SW_RESTORE
- SW_SHOW
- SW_SHOWMAXIMIZED
- SW_SHOWMINIMIZED
- SW_SHOWMINNOACTIVE
- SW_SHOWNA
- SW_SHOWNOACTIVATE
- SW_SHOWNORMAL
说明: 按nCmdShow方式显示窗体
编写流程图:
代码样例:
在对话框上建立一个 Tab Control 控件,然后为控件添加关联的控制变量,并为变量命名为 m_tab.资源对话如下图所示:
添加两个对话框资源并为对话框资源定义相关属性,资源 ID 为IDD_PAGE1,IDD_PAGE2,资源视图如下所示:
为主对话框添加相关成员变量(属性页关联对象,CDialog 数组指针,当前显示标签页的索引)代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//Tab Control 控件关联变量 CTabCtrl m_tab; //记录当前显示页面的索引 int m_CurSelTab; //属性页对话框对象 CPage1 m_p1; CPage2 m_p2; //对话框数组 CDialog* pDialog[2];
在主对话框的 OnInitDialog 函数中初始化 Tab Control 控件,即在 OnInitDialog 函数中添加一下代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//创建两个对话框,并将 CTabCtrl 对象作为其父窗口 m_p1.Create(IDD_PAGE1, &m_tab); m_p2.Create(IDD_PAGE2, &m_tab); //把对话框对象与 CDialog 数组联系起来 pDialog[0] = &m_p1; pDialog[1] = &m_p2; //为 Tab Control 增加两个页面 m_tab.InsertItem(0, _T("One")); m_tab.InsertItem(1, _T("Two")); //获得 Tab Control 客户区矩形大小 CRect rc; m_tab.GetClientRect(&rc); //调整矩形大小让属性页显示在适当的位置上 rc.top += 23; rc.bottom -= 2; rc.left += 2; rc.right -= 3; //移动对话框窗口到矩形区域中 m_p1.MoveWindow(&rc); m_p2.MoveWindow(&rc); //显示初始页面,保存当前选择 pDialog[0]->ShowWindow(SW_SHOW); pDialog[1]->ShowWindow(SW_HIDE); m_CurSelTab = 0;
为 Tab Control 控件添加响应标签页选择改变事件( 即 TCN_SELCHANGE 事件),然后在事件响应函数中添加切换属性页操作,相关代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//把当前的页面隐藏起来 pDialog[m_CurSelTab]->ShowWindow(SW_HIDE); //得到新的页面索引 m_CurSelTab = m_tab.GetCurSel(); //把新的页面显示出来 pDialog[m_CurSelTab]->ShowWindow(SW_SHOW);
运行结果: