1、对话框中的控件
基本控件:
常用控件:
2、对话框的创建和显示
对话框分为两种:模态对话框和非模态对话框。模态对话框指当其显示时,其它程序会暂停执行,即不能进行其它操作,直到关闭这个对话框。非模态对话框则没有这个限制。
要创建一个对话框,需要先创建一个对话框资源:在“资源视图”中插入对话框资源,可以在其属性中设置其ID。
在MFC中,对资源的操作是通过对应的类来完成的,对话框资源类为CDialog。对话框资源创建完成后就可以为该资源添加一个相关联的类:右击对话框资源-添加类-输入类名(也可以直接双击对话框资源)。
CDialog::DoModal()用来创建一个模态对话框,eg:
CTestDlg dlg;
dlg.DoModal();
CDialog::Create()用来创建非模态对话框,函数原型:
virtual BOOL Create( LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL ); virtual BOOL Create( UINT nIDTemplate, CWnd* pParentWnd = NULL );第一个参数为对话框模板的名称或对话框资源ID,第二个参数指定对话框的父窗口。
创建非模态对话框后还要调用ShowWindow()函数将对话框显示出来,eg:
CTestDlg* pDlg = new CTestDlg;
dlg.create(IDD_DIALOG1, this);
dlg.ShowWindow(SW_SHOW);
对话框资内存的销毁动作可以重载CDialog(CWnd)类的PostNcDestroy()函数,在其中添加代码:
delete this;
3、为按钮控件添加单击消息响应函数
右击按钮,选择添加事件处理函数,消息类型选择BN_CLICKED,选择按钮所在对话框类,编辑函数名。
CWnd对象都有一个public成员变量m_hWnd,其用来保存与窗口对象相关联的窗口的句柄,如果CWnd对象没有与任何窗口相关联,m_hWnd即为NULL。可依据此来进行相关判断。
4、控件的调整
复制控件:按住Ctrl,用鼠标拖动相应控件到目的位置即可;调整各控件的位置及间距:可利用工具栏上相关工具实现。
静态控件的ID都是IDC_STATIC,如果想要其来响应鼠标点击事件,则需要更改其ID,还需要设置其Notify属性,使其可以像父窗口发送通告消息。
5、控件的访问
1、CWnd::GetDlgItem()用来获得对话框上指定控件的指针,参数为控件ID。函数原型:
CWnd* GetDlgItem(int nID) const;
void GetDlgItem(int nID,HWND* phWnd) const;
CWnd::GetDlgCtrlID()返回指定控件的ID,因为顶层窗口不具有ID值,所以如果是顶层控件窗口则返回值为NULL。
CWnd::GetWindowText() /SetWindowText() 用来获得 /设置控件上的文本。
CWnd::GetDlgItemText() /SetDlgItemText() 用来获得 /设置指定控件上的文本,相当于:GetDlgItem() + GetWindowText()。
CWnd::GetDlgItemInt() /SetDlgItemInt() 用来获得 /设置指定控件上的数值。
2、将编辑框控件与对话框的成员变量相关联,实现对控件的访问:
将编辑框控件与对话框的成员变量相关联,然后通过这些成员变量来获取或设置编辑框控件上的文本,这是最简单的访问控件的方法。具体实现为:右击对话框—添加变量—控件变量—选择指定编辑框控件的ID—控件类别选择Value值类型—设置其最大、最小值—根据需要设置变量的访问方式、变量类型、名称—还可以在对话框类的构造函数中设置其初始显示值。
控件与其关联的成员变量的数据交换是通过对话框的DoDataExchange()函数完成的,可以看到为一个控件关联变量后在DoDataExchange()函数中会自动添加一个以DDX_开头的函数,如果设置了变量的最大、最小值,则会自动添加一个以DDV_开头的函数(DDX:Dialog Data Exchange即数据交换,DDV:Dialog Data Validation即数据校验)。在程序中并不直接调用DoDataExchange()函数,而是通过调用UpdateData()来调用它,当其参数为TRUE时,是从控件得到成员变量的值,当参数为FALSE时,是用成员变量的值来初始化控件。
故在使用与控件相关联的成员变量前,还需先调用UpdateData()来获得对话框上控件的数据;在改变了与控件相关联的成员变量的值以后,还需再调用UpdateData(FALSE)来初始化对话框上控件的内容。eg:
UpdateData();
m_iNum1 = m_iNum2 + m_iNum3;//与编辑框控件相关联的三个整形类型的成员变量
UpdateData(FALSE);
还可以将编辑框控件与控件变量相关联,即在控件类别中不选择Value而是选择Control,变量类别会自动变成CEdit。这个时候这个控件变量即代表了控件本身,调用控件变量的成员函数即为调用这个控件的成员函数。
需要注意的是向单选按钮添加空间变量的时候要将单选按钮的Group属性选择。
3、可以通过向控件发送WM_GETTEXE消息来获得控件上的文本;向控件发送WM_SETTEXT消息来设置控件上的文本。
SendDlgItemMessage()函数可以直接向对话框指定控件发送消息。
6、对话框分割线
可以通过拖拽图像控件成一条线来显示一条分割线,将其Sunken属性选中,会出现下陷效果。通过图像控件的成员函数GetWindowRect()可以获得分割线的矩形区域坐标,再调用对话框的GetWindowRect()获得对话框的矩形区域坐标,通过这两个矩形区域坐标可以计算出分割线上下区域的矩形坐标。如果不想让用户看到这条分割线,可以将图像控件的Visible属性去掉。
7、对话框上输入焦点的传递
窗口过程函数是在定义窗口类时设置的,当窗口已经创建之后,可以调用SetWindowLong()函数修改指定窗口的窗口过程。SetWindowLong()函数可以实现在窗口创建之后修改其属性,函数原型:
LONG WINAPI SetWindowLong(
HWND hWnd,
int nIndex,
LONG dwNewLong
);
hWnd:要修改的窗口的句柄
nIndex:要设置的属性值的偏移地址,可以为以下值:
GWL_STYLE:设置一个新的窗口样式(对应CreateWindow()函数的第三个参数)。
GWL_EXSTYLE:设置一个新的扩展窗口样式,如WS_EX_TOOLWINDOW为让窗体不在任务栏中显示。
GWL_WNDPROC:设置一个新的窗口过程函数。
GWL_HINSTANCE:设置一个新的应用程序实例句柄。
GWL_ID:为窗口设置一个新的标识。
GWL_USERDATA:设置与窗口相关的32位值,每个窗口均有一个由创建该窗口的应用程序使用的32位值。
若hWnd为一个对话框,则nIndex还可以是以下值:
DWL_DLGPROC:设置新的对话框过程函数。
DWL_MSGRESULT:设置在对话框过程函数中处理的消息返回值。
DWL_USER:设置新的额外信息,该信息仅为应用程序所有,例如句柄或指针。
dwNewLong:指定设置的新值。
SetWindowLong()调用成功会返回先前为窗口指定的32位整形值。如果是为窗口设置新的窗口过程,返回值即为窗口原来的窗口过程函数的地址。
GetWindowLong()可以获得指定窗口的属性信息,其参数与SetWindowLong()前两个参数意义相同。函数原型:
LONG WINAPI GetWindowLong(
HWND hWnd,
int nIndex
);
SetFocus()函数用来设置指定窗口为输入焦点。
GetFocus()函数获得当前焦点所在的窗口。
GetNextWindow()函数可以获得指定窗口(控件)的上一个或下一个窗口(控件)的指针(全局函数返回为句柄),参数为GW_HWNDNEXT则返回下一个窗口,参数为GW_HWNDPREV返回上一个窗口。
GetWindow()函数返回与指定窗口具有特定关系的窗口,利用该函数同样可以查找指定窗口(控件)的上一个或下一个窗口(控件)。
如果想让对话框工具箱上的编辑控件支持多行输入,则需要将编辑框控件的Multiline属性选中,并且只有编辑框支持多行输入才能接收回车键。
下面的代码为为对话框上ID为IDC_EDIT1的编辑框控件设置新的窗口过程:
LRESULT CALLBACK NewProc(
HWND hwnd, //消息所属窗口的句柄
UINT uMsg, //消息代码
WPARAM wParam, //消息附加参数
LPARAM lParam //消息附加参数
)
{
if(uMsg == WM_CHAR && wParam == 0x0d)//遇到回车键消息
{
::SetFocus(GetNextWindow(hwnd, GW_HWNDNEXT));//将下一个控件窗口设为焦点
return 1;
}
else
{
return OldProc(hwnd, uMsg, wParam, lParam);//其它消息使用原来的窗口过程处理
}
}
BOOL CDlgDlg::OnInitDialog()
{
......
oldProc = (WNDPROC)SetWindowLong(GetDlgItem(IDC_EDIT1)->m_hWnd, GWL_WNDPROC, (LONG)NewProc);
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
GetNextDlgTabItem()函数可以获得指定控件的前一个或后一个具有WS_TABSTOP风格的控件。工具箱上的按钮控件、编辑框控件等控件的Tabstop属性默认是选中的,即它们默认具有WS_TABSTOP风格,静态控件默认是不具有WS_TABSTOP风格的。用户按下Tab键后,输入焦点可以转移到具有WS_TABSTOP风格的控件上。GetNextDlgTabItem()的第一个参数指定被搜索的对话框,第二个参数为搜索起始控件,第三个参数为搜索方向:TRUE为搜索对话框中上一个控件,FALSE为搜索对话框中下一个控件。
调用GetNextWindow()或GetWindow()获得下一个窗口会有一个问题,那就是当对话框的最后一个控件调用此函数时,返回值为NULL。而调用GetNextDlgTabItem()则不会出现这个问题,因为它是按照对话框的Tab顺序来循环查找下一个控件的。对话框的Tab顺序可以点击菜单栏上"格式"下的"Tab键顺序"进行查看,可以自定义其顺序。