单选钮
图6. 29 单选钮示例程序
单选钮用来表示一系列的互斥选项,这些互斥选项常常被分成若干个组。下面的示例程序说明了单选钮的使用。
1. 创建新的基于对话框的MFC应用程序,将工程名设置为RadioButton。
2. 按图6.29绘制应用程序的主对话框。其中在Control工具箱中单选钮对应的图标是,组框控件对应的图标是。
3. 单击Layout菜单下的TabOrder命令,按图6.30的顺序单击各控件以设置控件的TAB键顺序(Tab Order)。
4. 确信所有控件的Group属性都被设置为假。分别单击组框“性别”和组框“年龄”,将其Group属性设置为真。
图6. 30 设置控件的Tab Order
以TabOrder为序,从Group属性为真的控件开始(包括该控件),到下一个Group属性的真的控件结束(不包括该控件),所有的这些控件将组成一个组。对于单选钮,同一组内同时只能有(也应该有)一个处于被选中的状态。当其中一个控件被置于选中状态时,同组的其它单选钮应该清除其选中状态。对于由资源编辑器生成的单选钮控件,在默认情况由Windows自动处理同组控件之间的互斥关系。
下面我们简述一下特定于单选钮的一些属性及其含义,这些属性被列于Styles选项卡内:
Auto: | 在具有Auto属性的情况下,当用户单击了同一组的某个单选钮时,其余单选钮的选中属性被自动清除。当在一组单选钮中使用Dialog Data Exchange时,该属性必须被设置为True。类型:布尔值 默认值:真 |
Left text: | 将单选钮的标题文本显示于圆形标记的左边。类型:布尔值 默认值:假 |
Push-like: | 使一个复选框、三态复选框或单选项具有类似于下压按钮的外观和行为。该按钮在选中时显示为凸起,在不被选中时显示为凹下(参见图。类型:布尔值 默认值:假 |
Notify: | 决定在默认情况下当单选钮被单击或双击时向父窗口发送通知消息。类型:布尔值 默认值:真 |
图6. 31 具有Pusk-like样式的单选钮
5. 将性别框内的两个控件的ID按从上到下的顺序设置为IDC_SEX1和IDC_SEX2;将年龄框内的两个控件的ID按从上到下的顺序设置为IDC_AGE1、IDC_AGE2、IDC_AGE3、IDC_AGE4和IDC_AGE5。
在程序运行时可以调用CButton的成员函数SetCheck设置单选钮的选中状态。该成员函数带有一个类型为整型的参数,该参数为0表示清除选中按钮的选中状态,参数为1表示设置选中按钮的选中状态。
- 注意:
- 如果我们在程序中调用SetCheck设置同一组中某一单选钮的为选中状态,并不意味着同时清除同一组中其它单选钮的选中状态。以前面创建的工程来举例,请看下面的两行代码:
- ((CButton*)GetDlgItem(IDC_AGE1))->SetCheck(1);
- ((CButton*)GetDlgItem(IDC_AGE5))->SetCheck(1);
上面的代码将导致年龄组中的第一个按钮和第五个按钮在对话框第一次显示时同时处于选中状态。这是应该避免的。因此,如果我们通过代码改变了单选钮的选中状态,一定要记得同时清除同组的其它单选钮的选中状态。
对于单个的单选钮,我们可以调用类CButton的成员函数GetCheck,该函数的返回值为0、1或2,分别代表按钮处理未选中状态、选中状态或中间状态(对三态复选框而言)。但是,对于对话框中的单选锯而言,我们更感兴趣于同一组单选钮中哪一个被选中,因此,调用类CWnd的成员函数GetCheckedRadioButton要更为方便。该成员函数原型如下:
int GetCheckedRadioButton( int nIDFirstButton, int nIDLastButton );
第一个参数nIDFirstButton是同一组中的第一个单选钮控件的ID,nIDLastButton是同一组中最后一个单选钮控件的ID。成员函数GetCheckedRadioButton返回指定组中第一个所选中的单选钮(在正常情况下仅应当有一个单钮被选中)的ID,如果没有按钮被选中,则返回0。
这里需要注意的是,成员函数GetCheckedRadioButton被没有要求两个参数nIDFirstButton和nIDLastButton所指定的控件一定位于同一组中。
- 注意:
- 若干个单选钮是否属于同一组是以其Tab顺序来排定的,而GetCheckedRadioButton函数是以ID顺序来检查按钮的选定状态的。因此,如果传递给函数GetCheckedRadioButton的第一个参数的值大于第二个参数的值时,其返回值总是为0,而事实上,由这两个参数指定的单选钮的TAB顺序可能恰恰相反。因此,一般情况下我们应该尽量保证同一组单选钮的资源ID是连续递增的。通常这些资源ID是在头文件Resource.h中定义的。如果你同一组的单选钮不是一次创建的,那么它们的资源ID可能不是连续递增的,甚至可能是相反的。这时我们可以手动的修改资源头文件中的宏定义,以保证如GetCheckedRadioButton之类的成员函数得到正确的结果。
同时,这也说明一点,即使用GetCheck一个一个控件的检查各单选钮的选中状态要安全得多。
下面我们来完成应用程序RadioButton。
首先,使用ClassWizard重载类CDialog的OnOK成员函数,方法是重载ID为IDOK的按钮的BN_CLICKED命令处理函数。由ClassWizard生成的默认重载形式如下:
void CRadioBoxDlg::OnOK()
{
// TODO: 在此添加附加的验证
CDialog::OnOK();
}
这里特定的代码来替代前面的// TODO注释后得到如下的程序代码:
void CRadioBoxDlg::OnOK()
{
// 暂时隐藏主对话框
ShowWindow(SW_HIDE);
UINT nSex=GetCheckedRadioButton(IDC_SEX1,IDC_SEX2); // 获得性别选择
UINT nAge=GetCheckedRadioButton(IDC_AGE1,IDC_AGE5); // 获得年龄选择
CString msg="性别: "; // 保存输出消息字符串
// 根据用户的选择生成消息串
// 添加性别信息
switch (nSex)
{
case IDC_SEX1:
msg+="男\n";
break;
case IDC_SEX2:
msg+="女\n";
break;
default:
break;
}
// 添加年龄信息
msg+="年龄: ";
switch (nAge)
{
case IDC_AGE1:
msg+="18 岁以下";
break;
case IDC_AGE2:
msg+="18 - 25 岁";
break;
case IDC_AGE3:
msg+="25 - 35 岁";
break;
case IDC_AGE4:
msg+="35 - 45 岁";
break;
case IDC_AGE5:
msg+="45 岁以上";
break;
default:
break;
}
msg+="\n\n以上数据是否正确?";
// 显示输入消息框询问用户所输入的信息是否正确
if(MessageBox(msg,NULL,MB_YESNO|MB_ICONQUESTION)==IDNO)
{
// 当用户回答“否”时重新显示对话框以供便用户可以更改所作的选择
ShowWindow(SW_SHOW);
return;
}
// 否则退出应用程序
CDialog::OnOK();
}
以上应用程序的运行结果如图6.32所示:
按如图6.32所示进行选择,单击确定弹出如图6.33所示的对话框。
下一节中我们将讲述复选框的使用。
图6. 32 单选钮示例程序的运行结果
图6. 33 单击“确定”之后的确认消息框