第八课:对话框第二部分
1. 逃跑按钮的巧妙实现:
首先建立一个对话框程序,再建立两个一样的按钮,使其中一个的属性设为不可见,我们要捕获按钮的WM_MOUSEMOVE消息,所以要先建一个按钮的CRunBtn类,并且把两个按钮进行控件关联到m_btn1和m_btn2,以CRunBtn为基类,就可以响应WM_MOUSEMOVE消息了。在OnInitialDialog中交换两个变量的内存地址,如何交换呢,就是建立一个CRunBtn类的一个指针变量m_pBtn。交换代码如下:m_btn1.m_pBtn=&m_btn2; m_btn2.m_pBtn=&m_btn1;
这个我不理解为什么这样可以交换内存地址。然后在OnMouseMove中添加代码:ShowWindow(SW_HIDE); m_pBtn->ShowWindow(SW_SHOW);
用SetWindowPos实现目前还没有解决,网上的方法也不可行哎。
2.创建属性表单→创建属性页
先创建3个属性页,通过右键Dialog→插入→IDD_PROPPAGE_LARGE,这里最好将属性中的字体改为中文,因为我们在后面将用到中文输入。
在属性页中添加组合框时要注意(Combo Box)它有三个选择:在样式中可以选择是只能下拉选择,还是能输入的组合框。
那么如何做呢,msdn中查找CPropertyPage是这么介绍的:
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. Call CPropertySheet::AddPage for each page in the sheet, and then display the property sheet by calling CPropertySheet::DoModal for a modal property sheet, or CPropertySheet::Create for a modeless property sheet.
大体的意思就是我们在属性表单中为每一个CPropertyPage派生一个类,首先创建一个CPropertySheet类对象,然后在CPropertySheet中为每一个属性页创建一个对象,在构造函数中为每一个属性页调用CPropertySheet::AddPage,然后调用CPropertySheet::DoModal将它显示出来。显示对话框是在View中完成的,为View类添加一个类向导,
void CPropView::OnShowPropSheet()
{
// TODO: Add your command handler code here
CPropSheet propSheet("职业属性表单",this,0);
propSheet.SetWizardMode();//这个表示创建的是向导类的。
propSheet.DoModal();
}
要使得CPropertySheet中的back、next等不可用,则可调用CPropertySheet::SetWizardButtons。Typically, you should call SetWizardButtons from CPropertyPage::OnSetActive.因此我们在CPropertyPage派生的类中添加OnSetActive的虚函数进行覆盖,实现我们的需求。
然后我们实现让使用者如果不选择相应的选项就不让他进入下一步,通过添加函数
还要为组框和列表框关联变量。
LRESULT CProp1::OnWizardNext()
{
// TODO: Add your specialized code here and/or call the base class
UpdateData();//这里一定要加
if(m_occupation==-1)
{
MessageBox("请选择你的职业!");
return -1;//若为-1则不进入下一步。
}
if(m_workAddr=="")
{
MessageBox("请选择你的工作地点!");
return -1;
}
return CPropertyPage::OnWizardNext();
}
初始化列表框则用:
((CListBox*)GetDlgItem(IDC_LIST1))->AddString("杭州");
((CListBox*)GetDlgItem(IDC_LIST1))->AddString("美国");
((CListBox*)GetDlgItem(IDC_LIST1))->AddString("西班牙");
在第三个属性页中要使自动选择一个选项可调用
CComboBox::SetCurSel这个函数。
为最后一个属性页类添加一个虚函数OnWizardFinish()当单击完成按钮时,将用户的选择存入m_strSarlary中。
int index;
index=((CComboBox*)GetDlgItem(IDC_COMBO1))->GetCurSel();
((CComboBox*)GetDlgItem(IDC_COMBO1))->GetLBText(index,m_strSarlary);
然后在CPropView类中为对应3个属性页面添加变量,存储属性页选择的内容。并进行窗口重绘使得我们可以在OnDraw函数中输出相应选择的内容:
CPropSheet propSheet("职业属性表单",this,0);
propSheet.SetWizardMode();
if(ID_WIZFINISH==propSheet.DoModal())
{
m_nOccupation=propSheet.m_prop1.m_occupation;
m_strWorkAddr=propSheet.m_prop1.m_workAddr;
m_like[0]=propSheet.m_prop2.m_car;
m_like[1]=propSheet.m_prop2.m_plane;
m_like[2]=propSheet.m_prop2.m_qq;
m_like[3]=propSheet.m_prop2.m_love;
m_strSarlary=propSheet.m_prop3.m_strSarlary;
Invalidate();//窗口重绘。
}
在OnDraw函数中先为要输出的文本创建字体,这里我们选择幼圆,然后创建一个临时变量strTemp储存要输出的内容。
void CPropView::OnDraw(CDC* pDC)
{
CPropDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CFont font;
font.CreatePointFont(150,"幼圆");
CFont *pOldFont;
pOldFont=pDC->SelectObject(&font);
CString strTemp="你的职业是:";
switch(m_nOccupation)
{
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;
pDC->GetTextMetrics(&tm);
pDC->TextOut(0,tm.tmHeight,strTemp);
strTemp="你的兴趣爱好是:";
if(m_like[0])
{
strTemp+="飙车 ";
}
if(m_like[1])
{
strTemp+="开飞机 ";
}
if(m_like[2])
{
strTemp+="qq ";
}
if(m_like[3])
{
strTemp+="love ";
}
pDC->TextOut(0,tm.tmHeight*2,strTemp);
strTemp="你的薪资水平是:";
strTemp+=m_strSarlary;
pDC->TextOut(0,tm.tmHeight*3,strTemp);
pDC->SelectObject(pOldFont);
// TODO: add draw code for native data here
}
还要注意的是GetTextMetrics是取一个字体而GetTextExtend取的是一个字符串