第7章 对话框(一)
1.对话框基本知识
在MFC中所有的控件类都是由CWnd类派生来的,因此控件实际上也是窗口,控件通常是作为对话框的子窗口而创建的。另外控件也可以出现在视类窗口、工具栏和状态条中。控件是独立的小部件,在对话框与用户的交互过程中担任着主要角色。
对话框的种类:
①模态对话框:当其显示时程序会暂停执行,直到关闭这个模态对话框后,才能继续执行程序中的其他任务;
②非模态对话框:非模态对话框显示时允许程序转而执行其他任务,而不用关闭这个对话框。
2.对话框的创建和显示
对话框作为资源插入到项目中。在MFC中,对资源的操作通常都是通过一个与资源相关的类来完成的,对话框资源也有一个相应的基类:CDialog,他派生自CWnd类。可以通过类向导为对话框资源新建相关联的类。例如为资源ID号为IDD_DIALOG1的对话框新建了一个CTestDlg类,则在该类中有两个成员函数,其一为构造函数:
CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTestDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CTestDlg)
//NOTE:the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
由CTestDlg的头文件中可知,IDD即为IDD_DIALOG1:
//{{AFX_DATA(CTestDlg)
enum { IDD = IDD_DIALOG1 };
//}}AFX_DATA
另一个函数为DoDataExchange,主要用来完成对话框数据的交换和校验:
void CTestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTestDlg)
//NOTE:the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
模态对话框的创建:
CTestDlg dlg;
dlg.DoModal();
dlg.EndDialog();
非模态对话框的创建:
CTestDlg *pDlg=new CTestDlg;
pDlg->Create(IDD_DIALOG1,this);
pDlg->ShowWindow(SW_SHOW);
在创建非模态对话框时不能把对话框对象定义为局部变量,解决方法有两种:一是把对话框变量定义为视类的成员变量;第二种方法是将其定义为指针,在堆上分配内存,在堆上分配的内存与程序的整个生命周期是一致的。对于模态对话框则不存在这个问题,因为在调用DoModal函数显示时,程序会暂时停止执行,直到模态对话框关闭以后程序才继续向下执行。
当点击对话框上的OK按钮时,对于模态对话框而言,此时对话框窗口对象被销毁了,但是对于非模态对话框而言,对话框窗口对象并未被销毁,只是隐藏起来了。因此对于非模态对话框来说,必须重写响应的按钮响应函数,并在重写的函数中调用DestroyWindow函数,同时注意不要再调用基类的相应函数。
控件的访问
为了使一个静态文本控件能够响应鼠标单击事件,需要进行两个特殊的步骤:首先改变它的ID,使其不为默认的IDC_STATIC,其次在它的属性对话框中选中Notify。
对话框控件访问的七种方式
①GetDlgItem(ID)->Get(Set)WindowText()
②GetDlgItemText()/SetDlgItemText()
③GetDlgItemInt()/SetDlgItemInt()
④将控件和整型变量(Value)相关联:将编辑框与对话框的成员变量相关联,然后通过成员变量来检索和设置编辑框的文本。
当为ID为IDC_EDIT1的编辑框控件添加了一个关联的int型成员变量m_num1后,ClassWizard添加了以下内容:
1)在CTestDlg类的头文件中两个AFX_DATA注释宏之间增加了一个成员变量:
// Dialog Data
//{{AFX_DATA(CTestDlg)
enum { IDD = IDD_DIALOG1 };
int m_num1;
//}}AFX_DATA
2)在CTestDlg类的构造函数中对其进行了初始化,赋值为0:
CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTestDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CTestDlg)
m_num1 = 0;
//}}AFX_DATA_INIT
}
3)在DoDataExchange函数内部实现了对话框控件与类成员变量的关联:
void CTestDlg::DoDataExchange(CDataExchange* pDX)
{//CDataExchange提供了DDX、DDV运行所需的上下文信息
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTestDlg)
DDX_Text(pDX, IDC_EDIT1, m_num1);
//}}AFX_DATA_MAP
}
DoDataExchange函数由程序框架调用,以完成对话框数据的交换和校验。DDX_Text函数的功能就是将ID指定的控件与特定的类成员变量相关联。MFC提供了许多以DDX_为前缀的函数,这些函数分别用于不同控件的数据交换。在程序中从来不直接调用DoDataExchange函数,而是通过CWnd类的另一个函数UpdateData来调用。UpdateData函数有一个BOOL参数,如果其值为TRUE,则说明该函数正在获取对话框的数据,如果其值为FALSE,则说明该函数正在初始化对话框的控件,参数默认值为TRUE。
可以在类向导窗口中设置关联变量的取值范围,此时ClassWizard将自动添加数据校验函数。
⑤将控件和控件变量(Control)相关联
1)头文件:
//{{AFX_DATA(CTestDlg)
enum { IDD = IDD_DIALOG1 };
CEdit m_edit1;
2)DoDataExchange函数:
DDX_Control(pDX, IDC_EDIT1, m_edit1);
然后就可以像操纵控件本身一样来使用控件变量了。
⑥SendMessage()
Windows程序都是基于消息的系统,在Windows系统中获取窗口文本的消息是WM_GETTEXT、设置窗口文本的消息是WM_SETTEXT。可以利用SDK提供的SendMessage函数发送WM_GETTEXT消息获取文本,再发送WM_SETTEXT消息设置文本:
void CTestDlg::OnBtnAdd()
{
int num1,num2,num3;
char ch1[10],ch2[10],ch3[10];
SendMessage(GetDlgItem(IDC_EDIT1)->m_hWnd,WM_GETTEXT,10,(LPARAM)ch1);
SendMessage(GetDlgItem(IDC_EDIT2)->m_hWnd,WM_GETTEXT,10,(LPARAM)ch2);
num1 = atoi(ch1);
num2 = atoi(ch2);
num3 = num1 + num2;
itoa(num3,ch3,10);
::SendMessage(GetDlgItem(IDC_EDIT3)->m_hWnd,WM_SETTEXT,0,(LPARAM)ch3);
}//ENDOF CTestDlg::OnBtnAdd()
字符串与数值的转换:C语言提供了这样的转换函数atoi可以将一个由数字组成的字符串转换为响应的数值;itoa函数可以将一个数值转换为文本。
⑦SendDlgItemMessage():直接向对话框的子控件发送消息;
SendDlgItemMessage(IDC_EDIT1,WM_GETTEXT,10,(LPARAM)ch1);
获取窗口的大小和位置:GetWindowRect;
设置窗口的大小和位置:SetWindowPos;
当一个窗口已经创建之后,可以通过SetWindowLong函数来修改该窗口以指定的过程函数。当对话框及其上的子控件创建完成,将要显示之前会发送一个消息:WM_INITDIALOG。因此,在此消息的响应函数中修改窗口过程比较合适。SetWindowLong可用来修改窗口的诸多属性。
输入焦点的传递。。。