对话框编程2

来源:互联网 发布:动漫 惊艳 音乐 知乎 编辑:程序博客网 时间:2024/04/30 10:58

在VC6.0中,新建一个单文档MFC工程,取名Prop,其它的步骤默认。

属性表单的创建

插入三个属性页资源,Insert -> resource -> IDD_PROPPAGE_LAGE .

插入的属性页资源与通常的对话框有区别,查看属性即可。手动插入的属性页资源在默认情况下其More Styles属性是Disable 。其样式如下图,其中单选框的ID分别为:IDD_PROP1,IDD_PROP2,IDD_PROP3 。

还有就是:这三个对话框的More Styles 要取消选择 Disable 。

 

给这三个属性页资源分别添加三个类,选择相应的属性页 -> class wizard… -> Add Class… -> New… -> (Name:CProp1 Base,class:CPropertyPage,Dialog ID:IDD_PROP1),用这种方法,连续的建三个类,OK!

Objects of class CPropertyPage represent individual pages of a property sheet, otherwise known as a tab dialog box. As with standard dialog boxes, you derive a class from CPropertyPage for each page in your property sheet. To use CPropertyPage-derived objects, first create a CPropertySheet object, and then create an object for each page that goes in the property sheet. CallCPropertySheet::AddPage for each page in the sheet, and then display the property sheet by calling CPropertySheet::DoModal for a modal property sheet, orCPropertySheet::Create for a modeless property sheet.

You can create a type of tab dialog box called a wizard, which consists of a property sheet with a sequence of property pages that guide the user through the steps of an operation, such as setting up a device or creating a newsletter. In a wizard-type tab dialog box, the property pages do not have tabs, and only one property page is visible at a time. Also, instead of having OK and Apply Now buttons, a wizard-type tab dialog box has a Back button, a Next or Finish button, and a Cancel button.

For more information on establishing a property sheet as a wizard, see CPropertySheet::SetWizardMode. For more information on using CPropertyPage objects, see the article Property Sheets in Visual C++ Programmer's Guide.

保存工程,保存所有文件,再关闭这个工程,删除工程中的Prop.clw 文件,再打开工程,再打开ClassWizard… 对话框,提示是否重新从源文件中创建类,选择确定,创建一个属性表单, Insert -> New Class… ->(Name:CPropSheet,Base class:CPropertySheet,Dialog ID:IDD_PROP1),OK !!!

在CPropSheet类点右键,Add Member Variable… ,分别添加三个属性类(CProp1,CProp2,CProp3)的成员变量m_prop1,m_prop2,m_prop3. 

public
    CProp1 m_prop1;//
添加三个成员变量
 
    CProp2 m_prop2; 
    CProp3 m_prop3; 
    virtual ~CPropSheet();

然后添加属性表单,在CPropSheet的两个构造函数中添加:

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);
  
}  

并在PropSheet.h中包含三个属性页的类的头文件:

// CPropSheet

#include "Prop1.h"//包含三个属性页的类的头文件

#include "Prop2.h"

#include "Prop3.h"

CPropertySheet::AddPage

This method adds a CPropertyPage object to the property sheet. Add pages to the property sheet in the left-to-right order you want them to appear.

void AddPage(

CPropertyPage* pPage);

Parameters

pPage

Points to the page to be added to the property sheet. Cannot be NULL.

Remarks

AddPage adds the CPropertyPage::CPropertyPage object to the CPropertySheet object list of pages but does not actually create the window for the page. The framework postpones creation of the window for the page until the user selects that page.

When you add a property page using AddPage, the CPropertySheet is the parent of the CPropertyPage. To gain access to the property sheet from the property page, call CWnd::GetParent.

It is not necessary to wait until creation of the property sheet window to call AddPage. Typically, you will call AddPage before calling DoModal or Create.

If you call AddPage after displaying the property page, the tab row will reflect the newly added page.

添加一个属性表单菜单项,在Class Wizard… 中给他添加一个对View类的消息响应函数,

void CPropView::OnPropertysheet()  

    // TODO: Add your command handler code here 
    CPropSheet propSheet("
一个属性表单程序");//构造一个属性表单对象 
    propSheet.DoModal();//
显示一个模态的属性表单 
}
 

并且还包含头文件:#include "PropSheet.h"//包含属性表单头文件

运行,会发现,中文都是乱码显示的。这就要在资源里修改属性页对话框的语言,把IDD_PROP1, IDD_PROP2, IDD_PROP3这三个都改成中文,并将三个对话框的字体也改成宋体,这里组合框的类型设置为Drop List,

再运行,可以看到中文显示正常了!

向导的创建

在CPropView::OnPropertysheet()函数中添加:

void CPropView::OnPropertysheet()  

    // TODO: Add your command handler code here 
    CPropSheet propSheet("
一个属性表单程序");//构造一个属性表单对象 
    propSheet.SetWizardMode();//
创建导向对话框 
    propSheet.DoModal();//
显示一个模态的属性表单 

CPropertySheet::SetWizardMode

void SetWizardMode( );

Remarks

Call this member function to establish a property page as a wizard. A key characteristic of a wizard property page is that the user navigates using Next or Finish, Back, and Cancel buttons instead of tabs.

Call SetWizardMode before calling DoModal. After you call SetWizardMode, DoModal will return either ID_WIZFINISH (if the user closes with the Finish button) or IDCANCEL.

SetWizardMode sets the PSF_WIZARD flag.

运行,即可看到,属性表单变成了导向的模式。

修改第一页的上一页和最后一页的下一页,分别给三个属性表单的类添加虚函数OnSetActive(),并编辑它们的代码如下:

BOOL CProp1::OnSetActive()

{

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

    ((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_NEXT);//获取父窗口的指针

    return CPropertyPage::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();

}

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();

}

CPropertySheet::SetWizardButtons

void SetWizardButtons( DWORD dwFlags );

Parameters

dwFlags

A set of flags that customize the function and appearance of the wizard buttons. This parameter can be a combination of the following values:

  • PSWIZB_BACK   Back button
  • PSWIZB_NEXT   Next button
  • PSWIZB_FINISH   Finish button
  • PSWIZB_DISABLEDFINISH   Disabled Finish button

Remarks

Call this member function to enable or disable the Back, Next, or Finish button in a wizard property sheet. Call SetWizardButtons only after the dialog is open; you can't call SetWizardButtons before you call DoModal. Typically, you should call SetWizardButtons from CPropertyPage::OnSetActive.

If you want to change the text on the Finish button or hide the Next and Back buttons once the user has completed the wizard, call SetFinishText. Note that the same button is shared for Finish and Next. You can display a Finish or a Next button at one time, but not both.

CPropertyPage::OnSetActive

virtualBOOLOnSetActive();

Return Value

Nonzero if the page was successfully set active; otherwise 0.

Remarks

This member function is called by the framework when the page is chosen by the user and becomes the active page. Override this member function to perform tasks when a page is activated. Your override of this member function should call the default version before any other processing is done.

The default implementation creates the window for the page, if not previously created, and makes it the active page.

给属性表单添加判断

对第一个属性表单的程序员设置成属性中的为选中状态,然后选择Class Wizard… -> Member Variables -> (Class Name:CProp1,ID:IDC_RADID1) -> Add Variable -> (name:m_occupation,Categury:Value)

点击 OK! 给第一个单选按钮添加了一个组后,这样选中第一个单选按钮时它所关联的成员变量m_occupation的值就为0,选中第二个单选按钮时所关联的值就为1,选中第三个单选按钮时所关联的值就为2。这个组直接遇到下一个具有那个单选按钮的的属性被选中时,这个才结束。如果把项目经理的组的属性选中,那么程序员和软件工程师就是一组了,项目经理就是单独的一组了。还有一点要提的是,如下

CProp1::CProp1() : CPropertyPage(CProp1::IDD)

{

    //{{AFX_DATA_INIT(CProp1)

    m_occupation = -1;//当初始化为-1时,表明没有一个单选按钮被选中

    //}}AFX_DATA_INIT

}

添加一个虚函数OnWizardNext()对于这个属性表单的下一步进行响应,编辑代码:

LRESULT CProp1::OnWizardNext()  

    // TODO: Add your specialized code here and/or call the base class 
    UpdateData(TRUE);//
为真时,取回控件中的值 
    if(m_occupation==-1
    { 
        MessageBox("
请选择你的职业 "
); 
        return -1
    }
 
    return CPropertyPage::OnWizardNext(); 
} 

CPropertyPage::OnWizardNext

virtual LRESULT OnWizardNext();

Return Value

0 to automatically advance to the next page;  –1 to prevent the page from changing. To jump to a page other than the next one, return the identifier of the dialog to be displayed.

Remarks

This member function is called by the framework when the user clicks on the Next button in a wizard.

Override this member function to specify some action the user must take when the Next button is pressed.

For more information on how to make a wizard-type property sheet, see CPropertySheet::SetWizardMode.

CPropertySheet::SetWizardMode

void SetWizardMode( );

Remarks

Call this member function to establish a property page as a wizard. A key characteristic of a wizard property page is that the user navigates using Next or Finish, Back, and Cancel buttons instead of tabs.

Call SetWizardMode before calling DoModal. After you call SetWizardMode, DoModal will return either ID_WIZFINISH (if the user closes with the Finish button) or IDCANCEL.

SetWizardMode sets the PSF_WIZARD flag.

做工作地点的判断

给CProp1添加一个WM_INITDIALOG消息响应函数,这个消息是在对话框将要显示之前发送的,

BOOL CProp1::OnInitDialog()  

    CPropertyPage::OnInitDialog(); 
     
    // TODO: Add extra initialization here 
    (GListBox*)GetDlgItem(IDC_LIST1)->AddString("
北京"); 
    (GListBox*)GetDlgItem(IDC_LIST1)->AddString("
天津"); 
    (GListBox*)GetDlgItem(IDC_LIST1)->AddString("
上海
"); 
    return TRUE;  // return TRUE unless you set the focus to a control 
                  // EXCEPTION: OCX Property Pages should return FALSE 

CListBox::AddString

intAddString(LPCTSTRlpszItem);

Return Value

The zero-based index to the string in the list box. The return value is LB_ERR if an error occurs; the return value is LB_ERRSPACE if insufficient space is available to store the new string.

Parameters

lpszItem

Points to the null-terminated string that is to be added.

Remarks

Call this member function to add a string to a list box. If the list box was not created with the LBS_SORT style, the string is added to the end of the list. Otherwise, the string is inserted into the list, and the list is sorted. If the list box was created with the LBS_SORT style but not the LBS_HASSTRINGS style, the framework sorts the list by one or more calls to the

给IDC_LIST1控件在CProp1这个类上增加一个CString类型的成员变量m_workAddr。在CProp1::OnWizardNext()函数中增加:

LRESULT CProp1::OnWizardNext()

{

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

    UpdateData(TRUE);//为真时,取回控件中的值

    if(m_occupation==-1)

    {

        MessageBox("请选择你的职业");

        return -1;

    }

    if(m_workAddr=="") //对工作地点的选择进行判断

    {

        MessageBox("请选择你的工作地点!");

        return -1;

    }

    return CPropertyPage::OnWizardNext();

}

对第二个页面进行处理

在第二属性页中分别对四个复选框控件在CProp2上添加如下相应的成员变量:

BOOL    m_football;

    BOOL    m_basketball;

    BOOL    m_volleyball;

    BOOL    m_swim;

作判断,在CProp2上增加一个OnWizardNext虚函数,编辑代码:

LRESULT CProp2::OnWizardNext()  

    // TODO: Add your specialized code here and/or call the base class 
    UpdateData(); //
获得控件的值 
    if(m_football||m_basketball||m_volleyball||m_swim) //
判断第二个属性页 
    { 
        return CPropertyPage::OnWizardNext(); 
    } 
    else 
    { 
        MessageBox("
请选择你的兴趣爱好!
"); 
        return -1
    }
 

}

对第三个页面进行处理

对CProp3类添加一个OnInitDialog消息处理,编辑:

BOOL CProp3::OnInitDialog()  

    CPropertyPage::OnInitDialog(); 
     
    // TODO: Add extra initialization here 
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("1000
元以下"); 
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("1000
元至2000"); 
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("2000
元至3000"); 
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->AddString("3000
元以上"); 
    ((CComboBox*)GetDlgItem(IDC_COMBO1))->SetCurSel(0); //
设置第1个列表项被选中

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

如果要将显示的选项按输入的选项顺序显示,可以取消组合框属性的sort选项。

将用户的选择输出到View类当中

给CProp3增加成员变量,m_strSalary,类型CString;并增加虚函数OnWizardFinish,Add And Edit… 。

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(); 
}

CComboBox::SetCurSel

intSetCurSel(intnSelect);

Return Value

The zero-based index of the item selected if the message is successful. The return value is CB_ERR if nSelect is greater than the number of items in the list or if nSelect is set to –1, which clears the selection.

Parameters

nSelect

Specifies the zero-based index of the string to select. If –1, any current selection in the list box is removed and the edit control is cleared.

Remarks

Selects a string in the list box of a combo box. If necessary, the list box scrolls the string into view (if the list box is visible). The text in the edit control of the combo box is changed to reflect the new selection. Any previous selection in the list box is removed.

CPropertySheet::SetWizardMode

void SetWizardMode( );

Remarks

Call this member function to establish a property page as a wizard. A key characteristic of a wizard property page is that the user navigates using Next or Finish, Back, and Cancel buttons instead of tabs.

Call SetWizardMode before calling DoModal. After you call SetWizardMode, DoModal will return either ID_WIZFINISH (if the user closes with the Finish button) or IDCANCEL.

SetWizardMode sets the PSF_WIZARD flag.

 

作在View类中输出用户的选择,在PropView.h头文件中,添加成员变量用于存放用户的选择,

private:  //View类的成员变量用来,接收用户的选择 
    int m_iOccupation; 
    CSting m_strWorkAddr; 
    BOOL m_bLike[4]; 
    CString m_strSalary;
 

并在构造函数中初始化:

CPropView::CPropView()

{

    // TODO: add construction code here

    m_iOccupation=-1;//初始化-1,没有被选中

    m_strWorkAddr="";

    meset(m_bLike,0,sizeof(m_bLike));//将数组中的buff都初始化成0

    m_strSalary="";

}

并在CPropView::OnPropertysheet()函数编辑:

void CPropView::OnPropertysheet()  

    // TODO: Add your command handler code here 
    CPropSheet propSheet("
一个属性表单程序");//构造一个属性表单对象 
    propSheet.SetWizardMode();//
创建导向对话框 
    //propSheet.DoModal();//
显示一个模态的属性表单 
    if(ID_WIZFINISH==propSheet.DoModal())//
如果返回的是完成向导的消息 
        //
注:在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();//
让窗口无效,引起窗口的重绘 
 
    }
 
}

CWnd::Invalidate

voidInvalidate(BOOLbErase=TRUE);

Parameters

bErase

Specifies whether the background within the update region is to be erased.

Remarks

Invalidates the entire client area of CWnd. The client area is marked for painting when the next WM_PAINT message occurs. The region can also be validated before a WM_PAINT message occurs by the ValidateRect or ValidateRgn member function.

The bErase parameter specifies whether the background within the update area is to be erased when the update region is processed. If bErase is TRUE, the background is erased when the BeginPaint member function is called; if bErase is FALSE, the background remains unchanged. If bErase is TRUE for any part of the update region, the background in the entire region, not just in the given part, is erased.

Windows sends a WM_PAINT message whenever the CWnd update region is not empty and there are no other messages in the application queue for that window.

然后在OnDraw()函数中完成各种信息的输出,

void CPropView::OnDraw(CDC* pDC) 

    CPropDoc* pDoc = GetDocument(); 
    ASSERT_VALID(pDoc); 
    // TODO: add draw code for native data here 
    CFont font;//
创建一个字体 
    font.CreatePointFont(300,"
华文行楷"); 
     
    CFont *pOldFont;//
用于保存返回的先前的字体 
    pOldFont=pDC->SelectObject(&font); 
    //
将字体选择到构架窗口的DC,返回先前的字体保存到pOldFont 
 
    CString strTemp;//
定义一个临时变量 
    strTemp="
你的职业:"
 
    //
判断用户的选择 
    switch(m_iOccupation) 
    { 
    case 0
        strTemp+="
程序员"
        break
    case 1
        strTemp+="
系统工程师"
        break
    case 2
        strTemp+="
项目经理"
        break
    default
        break
    } 
    pDC->TextOut(0,0,strTemp);//
将选择的职业输出到屏幕 
     
    strTemp="
你的工作地址:"
    strTemp+=m_strWorkAddr; 
 
    TEXTMETRIC tm;//
定义一个METRIC 
    pDC->GetTextMetrics(&tm); 
    pDC->TextOut(0,tm.tmHeight,strTemp); 
 
    strTemp="
你的兴趣爱好:"
    if(m_bLike[0]) 
    { 
        strTemp+="
足球"
    } 
    if(m_bLike[1]) 
    { 
        strTemp+="
篮球"
    } 
    if(m_bLike[2]) 
    { 
        strTemp+="
排球"
    } 
    if(m_bLike[3]) 
    { 
        strTemp+="
游泳"
    } 
    pDC->TextOut(0,tm.tmHeight*2,strTemp); 
 
    strTemp="
你的薪资水平:"
    strTemp+=m_strSalary; 
    pDC->TextOut(0,tm.tmHeight*3,strTemp); 
 
    pDC->SelectObject(pOldFont);//
将字体选择回来
  
}

 

运行,OK , ^_^

 

 

 

 

 

原创粉丝点击