Visual C++ 常见控件使用指南
在创建和显示对话框之后,接下来要探讨的是如何使用对话框中的控件,并将这些控件与源代码进行关联。以下将详细介绍一些常见控件的使用方法。
1. 数据验证函数
有一些 DDV(对话框数据验证)函数用于验证数据范围,除了
DDV_MinMaxInt()
外,还有
DDV_MinMaxByte()
和
DDV_MinMaxDouble()
等函数,它们用于验证其他数值数据类型的范围。表 8.2 列出了两个 DDV 函数,其详细信息将在后续对应控件的部分进行讨论。
2. 常见控件概述
对话框资源编辑器可用于排列对话框中的控件,以实现所需的外观。同时,还可以为每个控件分配一个 ID,这些 ID 会在
resource.h
文件中声明,以便在代码中与控件进行交互。
除了常见控件,还有 ActiveX 控件。ActiveX 控件可以像常见控件一样放置在对话框中,其独特之处在于不一定用 C++ 编写。可以将用 Visual Basic 编写的 ActiveX 控件插入到 C++ 程序中,这为开发者提供了更多的控件选择。
由于可用的控件众多,无法逐一讨论其用法。下面将介绍 Visual C++ 中一些常见控件的使用,如按钮、编辑框、列表框和组合框等。掌握这些常见控件的使用后,使用其他控件也会变得类似。
3. 按钮控件
按钮控件是对话框中最常见的控件,主要有三种类型:标准按钮、复选框和单选按钮。
3.1 标准按钮
对话框中的“确定”和“取消”按钮就是标准按钮的例子。按下标准按钮时会生成
WM_COMMAND
消息,可以使用
ON_COMMAND()
宏将按钮的标识符与消息处理程序关联起来。
CDialog
类将
IDOK
映射到
OnOK()
处理程序,将
IDCANCEL
映射到
OnCancel()
处理程序。
可以使用“按钮属性”对话框为按钮分配合适的标识符。为按钮点击事件分配消息处理程序有两种方法:
1. 使用
ON_COMMAND()
宏。例如,若按钮标识符为
IDC_NEW_ENTRY
,可通过以下消息映射将其消息映射到
OnNewEntry()
函数:
ON_COMMAND(IDC_NEW_ENTRY, OnNewEntry)
这种方法处理按钮消息与处理其他资源的菜单项消息相同,若应用程序中有相同标识符的菜单项,选择该菜单项会产生与点击此按钮相同的效果。
2. 使用
ON_BN_CLICKED()
宏。例如:
ON_BN_CLICKED(IDC_NEW_ENTRY, OnNewEntry)
使用
ON_BN_CLICKED()
宏可使消息映射更易读,因为从宏名就能明确消息来自按钮点击。Visual C++ 中的类向导在生成消息映射项时会使用该宏。
3.2 复选框
复选框由标签和一个可勾选或取消勾选的框组成。勾选框内会显示一个小勾号。虽然复选框外观不像按钮,但行为与按钮类似。
可以使用“复选框属性”窗口为复选框分配标签和标识符。由于复选框本质上是按钮,所以可以使用
ON_COMMAND()
或
ON_BN_CLICKED()
宏来响应用户勾选操作。不过,通常不需要对复选框生成的消息进行响应,而是在用户关闭对话框或接受选择时,了解哪些复选框被选中。
为实现这一点,需要为对话框类中的每个复选框控件关联一个成员变量,然后使用
DDX_Check()
函数将复选框的数据传输到相应的成员变量。示例代码如下:
class HobbyDialog : public CDialog
{
private:
BOOL m_ckSports; // Sports check box
BOOL m_ckMusic; // Music check box
BOOL m_ckComputers; // Computers check box
protected:
virtual void DoDataExchange(CDataExchange*);
// remainder of class declaration
};
void HobbyDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX); // invoke parent's
DDX_Check(pDX, IDC_SPORTS, m_ckSports);
DDX_Check(pDX, IDC_MUSIC, m_ckMusic);
DDX_Check(pDX, IDC_COMPUTERS, m_ckComputers);
}
void HobbyDialog::OnOK()
{
// the parent's OnOK() invokes UpdateData()
CDialog::OnOK();
CString message("You like ");
if (m_ckSports)
message += "sports ";
if (m_ckMusic)
message += "music ";
if (m_ckComputers)
message += "computers";
MessageBox(message, "Hobbies");
}
3.3 单选按钮
单选按钮是一种特殊的复选框,同一组单选按钮中每次只能选择一个。可以将一组单选按钮视为一个整体,只需知道哪个按钮被选中即可。
为创建单选按钮组,需要为组中的第一个按钮选择“Group”样式,后续的单选按钮将属于同一组。
在对话框类中,只需为一组单选按钮添加一个整型成员变量,用于表示被选中按钮的索引(第一个按钮索引为 0,依次递增)。使用
DDX_Radio()
函数在对话框和成员变量之间传输数据。示例代码如下:
class ColorDialog : public CDialog
{
private:
int m_SelectedColor; // index of radio button group
protected:
virtual void DoDataExchange(CDataExchange*);
// remainder of class definition
};
void ColorDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Radio(pDX, IDC_RED, m_SelectedColor);
}
void CRadioButtonsDlg::OnOK()
{
CDialog::OnOK();
CString message("Your favorite color is ");
switch (m_SelectedColor)
{
case 0:
message += "red";
break;
case 1:
message += "green";
break;
case 2:
message += "blue";
break;
default:
message = "You did not select a color";
}
MessageBox(message, "Favorite color");
}
4. 静态控件
静态控件用于提供视觉显示,不涉及用户交互。常见的静态控件有文本控件和分组框控件。文本控件用于显示文本,分组框控件用于在一组单选按钮周围显示视觉边框。
所有静态控件共享相同的标识符
IDC_STATIC
,因为它们不生成消息,所以无需为其分配唯一 ID。
5. 编辑控件
编辑控件为用户提供输入文本的机制,窗口为用户提供单行文本输入区域。若输入文本超出控件宽度,可使用左右箭头在文本行内滚动。
编辑控件通常使用静态文本控件来描述所需输入的类型。使用
DDX_Text()
函数在编辑控件和对话框类的成员变量之间传输数据。
DDX_Text()
函数进行了重载,可用于传输字节、短整型、整型、长整型、浮点型、双精度型、
DWORD
和
UINT
等数值类型的数据。
无论输入的数据类型如何,都可以使用 DDV 函数验证数据。例如,
DDV_MaxChars()
函数可用于限制字符串的字符数,还有针对不同数值类型的 DDV 函数用于指定值的范围。
示例代码如下,展示了一个登录对话框的实现:
class LogonDialog : public CDialog
{
private:
CString m_Username;
CString m_Password;
protected:
virtual void DoDataExchange(CDataExchange*);
// remainder of class declaration
};
void LogonDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_PASSWORD, m_Password);
DDX_Text(pDX, IDC_USERNAME, m_Username);
DDV_MaxChars(pDX, m_Username, 10);
}
void LogonDialog::OnOK()
{
CDialog::OnOK();
if (m_Username == "raposa" && m_Password == "password")
MessageBox("Successfully logged in!", "Success");
else
MessageBox("Invalid user info!", "Error", MB_OK | MB_ICONERROR);
}
6. 列表框控件
列表框控件在可滚动窗口中显示字符串列表,有单选和多选两种类型。
6.1 列表框初始化
不能使用资源编辑器确定列表框中最初显示的字符串,需要创建
CListBox
对象,并调用其
AddString()
或
InsertString()
成员函数。通常在
OnInitDialog()
函数中完成此操作,该函数在对话框即将显示时由框架调用。示例代码如下:
BOOL TeamDialog::OnInitDialog()
{
CDialog::OnInitDialog();
// get a pointer to the list box
CListBox *teams = (CListBox *)GetDlgItem(IDC_TEAMS);
// add the teams
teams->AddString("Broncos");
teams->AddString("Packers");
teams->AddString("Steelers");
teams->AddString("Cardinals");
teams->AddString("Dolphins");
teams->AddString("Vikings");
return TRUE;
}
6.2 单选列表框
若列表框使用单选样式,
DDX_LBString()
函数会将选中的字符串传输到相应的成员变量中。若未选择任何项,成员变量将为空字符串。示例代码如下:
class TeamDialog : public CDialog
{
private:
CString m_Team;
protected:
virtual void DoDataExchange(CDataExchange*);
// remainder of class declaration
};
void TeamDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_LBString(pDX, IDC_TEAMS, m_Team);
}
void CListBoxDlg::OnDblclkTeams()
{
UpdateData(TRUE);
MessageBox(m_Team, "You selected ...");
}
6.3 多选列表框
多选列表框生成的消息与单选列表框相同,
DDX_LBString()
函数可用于将当前选中的项传输到
CString
成员变量中。但了解多选列表框中当前选中项通常用处不大,因为在多选列表框中,当前选中项可能刚刚被取消选择,所以通常不使用数据交换来处理这些列表框。
控件使用流程总结
graph LR
A[创建对话框] --> B[使用资源编辑器排列控件并分配 ID]
B --> C{选择控件类型}
C --> |按钮| D[处理按钮消息]
C --> |复选框| E[关联成员变量并使用 DDX_Check 传输数据]
C --> |单选按钮| F[创建组并关联成员变量使用 DDX_Radio 传输数据]
C --> |静态控件| G[无需特殊处理]
C --> |编辑控件| H[使用 DDX_Text 传输数据并使用 DDV 验证]
C --> |列表框| I[初始化列表框并处理选择项]
常见控件类型及处理方式总结
| 控件类型 | 特点 | 处理方式 |
|---|---|---|
| 标准按钮 |
按下生成
WM_COMMAND
消息
|
使用
ON_COMMAND()
或
ON_BN_CLICKED()
宏关联消息处理程序
|
| 复选框 | 可勾选或取消勾选 |
关联成员变量,使用
DDX_Check()
传输数据
|
| 单选按钮 | 同一组中只能选一个 |
关联成员变量,使用
DDX_Radio()
传输数据
|
| 静态控件 | 提供视觉显示,无用户交互 |
无需特殊处理,共享标识符
IDC_STATIC
|
| 编辑控件 | 提供文本输入 |
使用
DDX_Text()
传输数据,用 DDV 函数验证数据
|
| 列表框 | 显示字符串列表,有单选和多选类型 |
初始化列表框,单选用
DDX_LBString()
传输数据
|
7. 组合框控件
组合框结合了编辑框和列表框的功能,用户既可以从列表中选择一个选项,也可以直接在编辑框中输入内容。组合框有三种样式:下拉式组合框、下拉式列表框和简单组合框。
7.1 组合框的初始化
与列表框类似,组合框也不能直接使用资源编辑器来确定初始显示的字符串。需要创建
CComboBox
对象,并调用其
AddString()
或
InsertString()
成员函数来添加选项。通常在
OnInitDialog()
函数中完成初始化操作。示例代码如下:
BOOL ComboDialog::OnInitDialog()
{
CDialog::OnInitDialog();
// 获取组合框指针
CComboBox *combo = (CComboBox *)GetDlgItem(IDC_COMBO);
// 添加选项
combo->AddString("Option 1");
combo->AddString("Option 2");
combo->AddString("Option 3");
return TRUE;
}
7.2 处理组合框的选择事件
当用户从组合框中选择一个选项时,会生成
CBN_SELCHANGE
消息。可以使用
ON_CBN_SELCHANGE()
宏来处理这个消息。示例代码如下:
BEGIN_MESSAGE_MAP(ComboDialog, CDialog)
ON_CBN_SELCHANGE(IDC_COMBO, OnSelChangeCombo)
END_MESSAGE_MAP()
void ComboDialog::OnSelChangeCombo()
{
CComboBox *combo = (CComboBox *)GetDlgItem(IDC_COMBO);
int selIndex = combo->GetCurSel();
CString selectedText;
combo->GetLBText(selIndex, selectedText);
MessageBox(selectedText, "You selected");
}
8. 进度条控件
进度条控件用于显示任务的进度,它可以是水平的或垂直的。进度条有一个最小值、最大值和当前值。
8.1 初始化进度条
在对话框的
OnInitDialog()
函数中,可以设置进度条的最小值、最大值和初始值。示例代码如下:
BOOL ProgressDialog::OnInitDialog()
{
CDialog::OnInitDialog();
// 获取进度条指针
CProgressCtrl *progress = (CProgressCtrl *)GetDlgItem(IDC_PROGRESS);
// 设置最小值和最大值
progress->SetRange(0, 100);
// 设置初始值
progress->SetPos(0);
return TRUE;
}
8.2 更新进度条
在任务执行过程中,可以通过调用
SetPos()
函数来更新进度条的当前值。示例代码如下:
void ProgressDialog::UpdateProgress(int value)
{
CProgressCtrl *progress = (CProgressCtrl *)GetDlgItem(IDC_PROGRESS);
progress->SetPos(value);
}
9. 滑块控件
滑块控件允许用户通过拖动滑块来选择一个数值。滑块有一个最小值、最大值和当前值。
9.1 初始化滑块
在对话框的
OnInitDialog()
函数中,可以设置滑块的最小值、最大值和初始值。示例代码如下:
BOOL SliderDialog::OnInitDialog()
{
CDialog::OnInitDialog();
// 获取滑块指针
CSliderCtrl *slider = (CSliderCtrl *)GetDlgItem(IDC_SLIDER);
// 设置最小值和最大值
slider->SetRange(0, 100);
// 设置初始值
slider->SetPos(50);
return TRUE;
}
9.2 处理滑块的滑动事件
当用户拖动滑块时,会生成
NM_CUSTOMDRAW
或
WM_HSCROLL
(水平滑块)、
WM_VSCROLL
(垂直滑块)消息。可以使用相应的消息映射宏来处理这些消息。示例代码如下:
BEGIN_MESSAGE_MAP(SliderDialog, CDialog)
ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER, OnCustomDrawSlider)
END_MESSAGE_MAP()
void SliderDialog::OnCustomDrawSlider(NMHDR *pNMHDR, LRESULT *pResult)
{
CSliderCtrl *slider = (CSliderCtrl *)GetDlgItem(IDC_SLIDER);
int value = slider->GetPos();
CString message;
message.Format("Current value: %d", value);
MessageBox(message, "Slider Value");
*pResult = 0;
}
控件使用注意事项
- 资源管理 :在创建控件对象时,要确保在合适的时机进行资源的分配和释放,避免内存泄漏。
- 消息处理 :不同的控件会生成不同的消息,要正确使用消息映射宏来处理这些消息,确保程序的响应性和稳定性。
- 数据验证 :使用 DDV 函数对用户输入的数据进行验证,避免非法数据导致程序出现错误。
不同控件的使用场景建议
| 控件类型 | 使用场景 |
|---|---|
| 按钮控件 | 用于触发操作,如提交表单、关闭窗口等 |
| 复选框 | 用于选择多个选项的场景 |
| 单选按钮 | 用于从多个选项中选择一个的场景 |
| 编辑控件 | 用于用户输入文本或数值的场景 |
| 列表框 | 用于显示一组选项,用户可以选择一个或多个的场景 |
| 组合框 | 既需要用户输入,又提供选项供用户选择的场景 |
| 进度条控件 | 显示任务进度的场景 |
| 滑块控件 | 允许用户选择一个连续数值范围的场景 |
完整控件使用流程图
graph LR
A[创建对话框] --> B[使用资源编辑器排列控件并分配 ID]
B --> C{选择控件类型}
C --> |按钮| D[处理按钮消息]
C --> |复选框| E[关联成员变量并使用 DDX_Check 传输数据]
C --> |单选按钮| F[创建组并关联成员变量使用 DDX_Radio 传输数据]
C --> |静态控件| G[无需特殊处理]
C --> |编辑控件| H[使用 DDX_Text 传输数据并使用 DDV 验证]
C --> |列表框| I[初始化列表框并处理选择项]
C --> |组合框| J[初始化组合框并处理选择事件]
C --> |进度条| K[初始化进度条并更新进度]
C --> |滑块| L[初始化滑块并处理滑动事件]
通过以上对各种常见控件的介绍和示例代码,你可以在 Visual C++ 中灵活运用这些控件来创建功能丰富、交互性强的对话框和应用程序。在实际开发中,根据具体的需求选择合适的控件,并正确处理控件的消息和数据,将有助于提高程序的质量和用户体验。
超级会员免费看
73

被折叠的 条评论
为什么被折叠?



