首页 > 代码库 > 属性页对话框

属性页对话框

1、分类

  标签式和向导式

2、相关类

  CPropertyPage -属性页,其实就是一个对话框页面,父类是CDialog类

  CPropertySheet -属性表单,父类是CWnd类

  一个完整的属性页对话框由一个属性表单+多个属性页组成

  属性页资源与普通对话框资源的区别:

  属性页:

    技术分享

    技术分享

 

  对话框:

    技术分享

    技术分享

3、标签式属性页

  3.1插入属性页对话框资源,修改语言和字体,双击资源,生成相应的类,注意父类选择CPropertyPage类。

    创建一个单文档视图的MFC工程:Prop

    技术分享

    插入3个属性页:

      技术分享

      技术分享

      技术分享

      技术分享

      技术分享

      技术分享

      注意:①这里插入的3个属性页资源的语言均为“English(U.S.)”,须右击资源修改属性为中文语言

          技术分享

          技术分享

          技术分享

         ②3个属性页Page1、Page2、Page3的字体默认均为“MS Sans Serif”,点击“字体[O]...”按键修改字体为中文字体

利用MFC类向导生成相应的属性页类:

          技术分享

          技术分享

          技术分享

          技术分享

  3.2类视图下右击工程,选择添加新的类,父类是CPropertySheet类。

    技术分享

    技术分享

  3.3在属性表单中添加属性页对象,在属性表单类的构造函数中调用  CPropertySheet::AddPage

    首先在在属性表单对象CPropSheet的头文件PropSheet.h中分别把先前创建的三个属性页的头文件包含进来:

      #include "Prop1.h"

      #include "Prop2.h"

      #include "Prop3.h"

    然后在属性表单对象CPropSheet的头文件PropSheet.h中为三个属性页分别定义成员变量:

      public:

          CProp1 m_prop1;

          CProp2 m_prop2;

          CProp3 m_prop3;

    属性表单类有两个构造函数,在构造属性表单对象时,可任选其一构造函数,调用AddPage函数添加属性页对象:      

CPropSheet::CPropSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
    :CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
{
    AddPage(&m_prop1);
    AddPage(&m_prop2);
    AddPage(&m_prop3);
}

CPropSheet::CPropSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
    :CPropertySheet(pszCaption, pParentWnd, iSelectPage)
{
    AddPage(&m_prop1);
    AddPage(&m_prop2);
    AddPage(&m_prop3);
}

  3.4创建显示属性表单  CPropertySheet::Domodal()

    在Prop程序的主菜单上添加一个菜单项,用户单击这个菜单项后,程序显示属性表单;

      技术分享

    在视图类中添加该菜单项的消息响应函数

      技术分享

    在CPropView类的源文件开始部分包含CPropSheet类的头文件:

      #include "stdafx.h"

      #include "Prop.h"

 

      #include "PropDoc.h"

      #include "PropView.h"

      #include "PropSheet.h"

    在程序新添加的菜单项的响应函数中,调用DoModal函数显示一个模式化的属性表单:      

void CPropView::OnPropertysheet() 
{
    // TODO: Add your command handler code here
    CPropSheet propSheet("属性表单");
    propSheet.DoModal();
    
}

      构造的CPropSheet类型的属性表对象propSheet调用的是以标题为参数的属性表单构造函数;

  3.5当控件的值发生改变时,将应用按钮设置为可用  CPropertyPage::SetModified(TRUE);

  3.6消息处理(通过在页面类中添加虚函数的方式实现)

    CPropertyPage::OnApply

    CPropertyPage::OnOK

    CPropertyPage::OnCancel

4、向导式属性页

  4.1插入属性页对话框资源,修改语言和字体,双击资源,生成相应的类,注意父类选择CPropertyPage类。

  4.2类视图下右击工程,选择添加新的类,父类是CPropertySheet类。

  4.3在表单类中添加属性页对象,在构造函数中调用  CPropertySheet::AddPage

  ---------------------------------之前的步骤与标签式属性页中创建属性表单的实现步骤一致

  4.4创建和显示前,设置为向导模式  CPropertySheet::SetWizardMode    

void CPropView::OnPropertysheet() 
{
    // TODO: Add your command handler code here
    CPropSheet propSheet("属性表单");

    propSheet.SetWizardMode();

    propSheet.DoModal();
    
}

  4.5创建和显示  CPropertySheet::DoModal()

  4.6设置每个页面的向导按钮 

    1--在 CPropertyPage::OnSetActive() 函数中设置

    2--在属性页中获取表单对象的指针  GetParent()

    3--设置向导按钮  CPropertySheet::SetWizardButtons()

      void SetWizardButtons( DWORD dwFlags );

      dwFlags:PSWIZB_BACK / PSWIZB_NEXT / PSWIZB_FINISH / PSWIZB_DISABLEDFINISH

    首先在第一个属性页的类CProp1中右击添加虚函数OnSetActive,第一个属性页应该只有【下一步】和【取消】

      技术分享      

BOOL CProp1::OnSetActive() 
{
    // TODO: Add your specialized code here and/or call the base class
    ((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_NEXT);

    return CPropertyPage::OnSetActive();
}

    为第二个属性页CProp2添加OnSetActive虚函数,第二个属性页应该有【上一步】【下一步】和【取消】      

BOOL CProp2::OnSetActive() 
{
    // TODO: Add your specialized code here and/or call the base class
    ((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_BACK|PSWIZB_NEXT);
    
    return CPropertyPage::OnSetActive();
}

     再为第三个属性页CProp3添加OnSetActive函数,第三个属性页应该有【上一步】和【完成】    

BOOL CProp3::OnSetActive() 
{
    // TODO: Add your specialized code here and/or call the base class
    ((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_BACK|PSWIZB_FINISH);
    
    return CPropertyPage::OnSetActive();
}

    在资源窗口的第一个属性页资源上,为单选按钮组关联一个成员变量

      注意:单选按钮组的第一个单选按钮的属性中的“组”要勾选,以标识这几个单选按钮为一组,只能选择其一;

        技术分享

      利用MFC类向导添加成员变量:

        技术分享

      默认会在CProp1类的构造函数中将m_occupation变量初始化为-1

        技术分享

      在选中单选按钮组的第一个单选按钮时,关联的成员变量m_occupation的值变为0;选中第二个单选按钮变为1;选中第三个单选按钮变为2;

      为CProp1类添加OnWizardNext虚函数,完成对属性页上【下一步】按钮的命令响应:

        技术分享       

LRESULT CProp1::OnWizardNext() 
{
    // TODO: Add your specialized code here and/or call the base class
    //须调用UpdateData函数以调用DoDataExchange来完成控件与成员变量的数据交换
    UpdateData(TRUE);  
    
    if(m_occupation==-1){
        MessageBox("请选择你的职业");
        return -1;
    }
    
    return CPropertyPage::OnWizardNext();
}

    要在属性页显示前向列表框中添加显示内容,为CProp1类添加WM_INITDIALOG消息的响应函数OnInitDialog;列表框控件有个相应的MFC类:CListBox,利用其成员函数AddString可向列表框添加字符:      

BOOL CProp1::OnInitDialog() 
{
    CPropertyPage::OnInitDialog();
    
    // TODO: Add extra initialization here
    ((CListBox*)GetDlgItem(IDC_LIST1))->AddString("北京");
    ((CListBox*)GetDlgItem(IDC_LIST1))->AddString("上海");
    ((CListBox*)GetDlgItem(IDC_LIST1))->AddString("广州");
    ((CListBox*)GetDlgItem(IDC_LIST1))->AddString("深圳");

    return TRUE;  // return TRUE unless you set the focus to a control
                  // EXCEPTION: OCX Property Pages should return FALSE
}

      利用MFC类向导给列表框控件关联一个成员变量m_workAddr:

        技术分享

        技术分享        

LRESULT CProp1::OnWizardNext() 
{
    // TODO: Add your specialized code here and/or call the base class
    //调用UpdateData函数以调用DoDataExchange来完成控件与成员变量的数据交换
    UpdateData(TRUE);  
    
    if(m_occupation==-1){
        MessageBox("请选择你的职业");
        return -1;
    }

    if(m_workAddr==""){
        MessageBox("请选择你的工作地点");
        return -1;
    }
    
    return CPropertyPage::OnWizardNext();
}

      在资源窗口的第二个属性页资源上,为四个复选框分别关联成员变量

        技术分享

        程序自动将复选框控件关联的各个成员变量初始化,当复选框控件被选中时,所关联的成员变量的值为TRUE,否则为FALSE;

        技术分享

        为CProp2类添加OnWizardNext虚函数,以在点击【下一步】时检查用户是否点选复选框

        技术分享        

LRESULT CProp2::OnWizardNext() 
{
    // TODO: Add your specialized code here and/or call the base class
    UpdateData(TRUE);
    if(m_football || m_basketball || m_volleyball || m_swim){
        return CPropertyPage::OnWizardNext();
    }else{
        MessageBox("请选择你的兴趣爱好");
        return -1;
    }
    
}

      为第三个属性页的CProp3类添加WM_INITDIALOG消息的响应函数OnInitDialog;组合框对应的MFC类为CComboBox,利用该类的成员函数AddString向组合框控件的列表框中添加选项;

        技术分享        

BOOL CProp3::OnInitDialog() 
{
    CPropertyPage::OnInitDialog();
    
    // TODO: Add extra initialization here
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("10000元以下");
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("10000-20000元");
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("20000-30000元");
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("30000元以上");
    
    return TRUE;  // return TRUE unless you set the focus to a control
                  // EXCEPTION: OCX Property Pages should return FALSE
}

        要是组合框的下拉选项的顺序和添加的顺序一样,须勾选掉资源窗口中组合框资源的属性中样式里的“分类”:

        技术分享

        要使得组合框中在显示时有一个默认的选中项,须使用SetCurSel函数实现:

          int SetCurSel(int nSelect);

          参数为选项的位置索引;如果为-1,则将移除组合框的当前选项并清空编辑框中的内容;        

BOOL CProp3::OnInitDialog() 
{
    CPropertyPage::OnInitDialog();
    
    // TODO: Add extra initialization here
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("10000元以下");
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("10000-20000元");
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("20000-30000元");
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("30000元以上");

    ((CComboBox*)GetDlgItem(IDC_COMBO1))->SetCurSel(0);
    
    return TRUE;  // return TRUE unless you set the focus to a control
                  // EXCEPTION: OCX Property Pages should return FALSE
}

        为第三个属性页CProp3类添加成员变量:CString m_strSalary,用来接收用户的选择;给CProp3类添加虚函数:OnWizardFinish,用来处理【完成】按钮的单击消息;

          技术分享

          技术分享

          为了获取用户在第三个属性页CProp3中的组合框的选择项,须先利用GetCurSel函数获得组合框中当前选项的位置,再利用GetLBText函数获得组合框的相应位置的对应字符串;          

BOOL CProp3::OnWizardFinish() 
{
    // TODO: Add your specialized code here and/or call the base class
    int index;
    index=((CComboBox*)GetDlgItem(IDC_COMBO1))->GetCurSel();
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->GetLBText(index,m_strSalary);
    
    return CPropertyPage::OnWizardFinish();
}

          为了接收用户在向导类属性列表的各个属性页中的选择,在程序的视图类中须定义相应的成员变量来保存;

          技术分享

          技术分享

          技术分享

          技术分享

          然后在视图类的构造函数中初始化这些成员变量:          

CPropView::CPropView()
{
    // TODO: add construction code here
    m_iOccupation=-1;
    m_strWorkAddr="";
    memset(m_bLike,0,sizeof(m_bLike));  //对数组m_bLike进行快速初始化
    m_strSalary="";
}

          判断只有当用户点击的是【完成】按钮,程序才接收各个属性页中的选择项:          

void CPropView::OnPropertysheet() 
{
    // TODO: Add your command handler code here
    CPropSheet propSheet("属性表单");

    propSheet.SetWizardMode();

    if(ID_WIZFINISH==propSheet.DoModal()){
        m_iOccupation=propSheet.m_prop1.m_occupation;
        m_strWorkAddr=propSheet.m_prop1.m_workAddr;
        m_bLike[0]=propSheet.m_prop2.m_football;
        m_bLike[1]=propSheet.m_prop2.m_basketball;
        m_bLike[2]=propSheet.m_prop2.m_volleyball;
        m_bLike[3]=propSheet.m_prop2.m_swim;
        m_strSalary=propSheet.m_prop3.m_strSalary;
        Invalidate();
    }   
}

  4.7消息处理函数

    虚函数:

    OnSetActive()--当属性页被选中时,使其成为当前的活动页面

    OnCancel()--单击属性页的【取消】按钮时程序调用该虚函数

    OnWizardNext()--单击属性页上【下一步】按钮时程序调用该虚函数;如果返回0,则自动进入当前向导的下一个属性页;如果返回-1,属性页不发生变化;

    OnWizardBack()--单击属性页【上一步】按钮时程序调用该虚函数

    OnWizardFinish()--单击属性页【完成】按钮时程序调用该虚函数

 

属性页对话框