MFC原创教程:4.0 Prop:属性表单

来源:互联网 发布:医疗美容网络 编辑:程序博客网 时间:2024/06/05 22:37

VC++/MFC Window编程原创教程目录

1:设置一个属性表单
添加三个Dialog--IDD_PROPPAGE_LARGE资源,修改ID为:IDD_PROP1、2、3;
添加如下控件:





右键点击IDD_PROP1、2、3资源视图--添加类(类名CProp1、2、3,基类:CPropertyPage属性页类);
添加新类CPropSheet,基类为:CPropertySheet。一个属性表由一个CPropertySheet对象和一个或多个CPropertyPage对象构成。
为CPropSheet添加CProp1、2、3变量m_prop1、2、3。
在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);
}
最后在菜单增加子菜单(属性表单),改其ID为IDM_PROPERTYSHEET,添加CPropView下的COMMAND消息。代码:
void CPropView::OnPropertysheet()
{
 // TODO: 在此添加命令处理程序代码
 CPropSheet propSheet("属性表单程序");
 propSheet.SetWizardMode(); //加上此句代码表向导模式。不加,则是选择模式。
 propSheet.DoModal(); //显示方法与Dialog相似
}
若使用导模式,则需增加代码完善页面。
CProp1--属性--重写(虚函数)--添加OnSetActive() //选择的页面为活动页面时触发的函数。代码如下
BOOL CProp1::OnSetActive()
{
 // TODO: 在此添加专用代码和/或调用基类
 ((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_NEXT);  //属性表单是属性页的父窗口,所以可以使用GetParent()获取然后进行转换。SetWizardButtons(PSWIZB_NEXT)表向导第一页只有下一步可用。
//同理,在CProp2、3添加的OnSetActive()代码为:
((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_BACK | PSWIZB_NEXT);
((CPropertySheet*)GetParent())->SetWizardButtons(PSWIZB_BACK | PSWIZB_FINISH);

 return CPropertyPage::OnSetActive();
}
2.1:需要进行选择职业才能进入下一步。
将单选
选项的Group属性值设置为TRUE才能为选项关联变量,表该页的单选选项关联在同一组,下标为0、1、2...直到遇到下个单选选项的Group属性值为TRUE的另一组。
为"程序员IDC_RADIO1"关联变量(Value,int变量名m_occupation),在构造函数将其初始值设为-1(0的话表默认选择第一项了)。然后重写(虚函数)OnWizardNext,代码:
LRESULT CProp1::OnWizardNext()
{
 // TODO: 在此添加专用代码和/或调用基类
 UpdateData(); //DoDataExchange 框架与控件用来交流数据,呼叫UpdateData函数时才会被调用http://zhidao.baidu.com/question/89105522.html
 if(m_occupation==-1)
 {
  MessageBox("请选择你的职业");
  return -1; //返回-1表返回当前属性页;返回0表下一步
 }
 return CPropertyPage::OnWizardNext();
}
2.2:需要进行选择工作地点才能进入下一步。
为IDC_LIST1列表框关联一个变量(Value,CString,变量名m_workAddr)。
重写(虚函数)OnInitDialog (框架显示前响应),代码:
BOOL CProp1::OnInitDialog()
{
 CPropertyPage::OnInitDialog();

 // TODO:  在此添加额外的初始化
 ((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
 // 异常: OCX 属性页应返回 FALSE
}
2.3:第二页,需要选择兴趣爱好才能下一步。
为IDC_CHECK1、2、3、4分别添加变量m_football、m_basketball、m_volleyball、m_swin(Value,BOOL)
为CProp2重写nWizardNext
LRESULT CProp2::OnWizardNext()
{
 // TODO: 在此添加专用代码和/或调用基类
UpdateData();
 if(m_football || m_basketball || m_volleyball || m_swin)
 {
  return CPropertyPage::OnWizardNext();
 }
 else
 {
  MessageBox("请选择你的兴趣爱好");
  return -1;
 }
}
2.4:第三页,默认选择第一项。
重写(虚函数)OnInitDialog
BOOL CProp3::OnInitDialog()
{
 CPropertyPage::OnInitDialog();

 // TODO:  在此添加额外的初始化
 ((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
 // 异常: OCX 属性页应返回 FALSE
}

3:输出选项内容。
首先在CProp3定义一个CString m_strSalary变量接收选项内容。
为CProp3重写nWizardFinish。
BOOL CProp3::OnWizardFinish()
{
 // TODO: 在此添加专用代码和/或调用基类
 int index;  //接收索引
 index=((CComboBox*)GetDlgItem(IDC_COMBO1))->GetCurSel();
 ((CComboBox*)GetDlgItem(IDC_COMBO1))->GetLBText(index,m_strSalary);  //接收对应索引的文本
 return CPropertyPage::OnWizardFinish();
}

在View.h类手动添加变量:
 int m_iOccupation; //接收职业
 CString m_workAddr; //接收工作地点
 BOOL m_bLike[4]; //接收兴趣爱好
 CString m_strSalary; //接收工薪水平
初始化:
CPropView::CPropView()
{
 // TODO: 在此处添加构造代码
 m_iOccupation=-1;
 m_workAddr="";
 memset(m_bLike,0,sizeof(m_bLike)); //数组初始化。参数(首地址,初始值,数组长度)
 m_strSalary="";
}
然后是获取属性页各项的值:
void CPropView::OnPropertysheet()
{
 // TODO: 在此添加命令处理程序代码
 CPropSheet propSheet("属性表单程序");
 propSheet.SetWizardMode();

 if(propSheet.DoModal())  //窗口销毁之后。但此时对象还在!
 {
  m_iOccupation=propSheet.m_prop1.m_occupation;
  m_workAddr=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_swin;
  m_strSalary=propSheet.m_prop3.m_strSalary;
//添加一个BOOL变量初始化为FALSE,用在OnDarw的判断
  m_bDraw=TRUE;
  Invalidate(); //让窗口无效,引起窗口重绘。然后在OnDraw完成信息是输出
 }
}
void CPropView::OnDraw(CDC* pDC)  //把后面的注释取消
{
 CPropDoc* pDoc = GetDocument();
 ASSERT_VALID(pDoc);
 if (!pDoc)
  return;

 // TODO: 在此处为本机数据添加绘制代码
 if(m_bDraw==true)
 {
  CString strTemp; //接收输出的文本。
  TEXTMETRIC tm; //接收字体信息

  strTemp="你的职位:";
 
  switch(m_iOccupation) //根据单项选择索引赋值
  {
  case 0:
   strTemp+="程序员";
   break;
  case 1:
   strTemp+="系统工程师";
   break;
  case 2:
   strTemp+="项目经理";
   break;
  default:
   break;
  }
  pDC->TextOutA(0,0,strTemp); //输出职位

  pDC->GetTextMetrics(&tm);

  strTemp="你的工作地点:"+m_workAddr;
  pDC->TextOutA(0,tm.tmHeight,strTemp); //输出工作地点
  strTemp="你的兴趣爱好:";
  if(m_bLike[0]==true)
   strTemp+="足球 ";
  if(m_bLike[1]==true)
   strTemp+="篮球 ";
  if(m_bLike[2]==true)
   strTemp+="排球 ";
  if(m_bLike[3]==true)
   strTemp+="游泳 ";
  pDC->TextOutA(0,tm.tmHeight*2,strTemp); //输出兴趣爱好

  strTemp="你的薪资:"+m_strSalary;
  pDC->TextOutA(0,tm.tmHeight*3,strTemp); //输出薪资
 }

}