在MFC中,对资源的操作通常都是通过一个与资源相关的类来完成的。CDialog是对话框的基类,它派生于CWnd类,所以它是一个与窗口相关的类,主要用来在屏幕上显示一个对话框。默认有IDOk和IDCancel两个函数,起作用均为关闭窗体,只是返回值不一样罢了。需关注两个函数: 1.构造函数:有两个参数:其一为CTestDlg类的IDD成员对话框的资源ID,一个是父窗口指针。 CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/) :CDialog(CTestDlg::IDD, pParent){} // enum { IDD = IDD_DIALOG1 }; 2.DoDataExchange是一个虚函数,主要用那个来完成对话框数据的交换和检验。 接下来,我们来说一下模态和非模态对话框。 1.模态对话框:当它显示时,程序会暂停执行,直到关闭这个模态对话框后,才能继续执行程序中其它任务。它实质上是垄断了用户的输入,当这个模态对话框打开时,用户只能与该对话框进行交互,而其他用户界面对象接收不到输入信息。注意模态对话框显示时,生命周期并未结束。 CTestDlg dlg; dlg.DoModal(); 2.非模态对话框:它在显示时,允许转而执行程序中的其他任务,而不关闭这个对话框,可以更好地进行交互。 需要注意:不能这样定义CTestDlg dlg然后创建对话框,这涉及到一个生命周期,因为一旦CTestDlg的生命周期结束了,就会销毁与之相关联的对话框资源。两种解决方法,第一种:把这个对话框资源定义为一个成员变量,另一种方式将它定义为指针,在堆上分配内存。在堆上分配内存与程序的整个生命周期一致。 CTestDlg* pDlg = new CTestDlg; pDlg->Create(IDD_DIALOG1,this); //当利用Create函数创建非模态对话框时,还需要用ShowWindow函数将这个对话框显示出来。 pDlg->ShowWindow(SW_SHOW); 指针变量pDlg是一个局部对象,这样当它的生命周期结束时,它所保存的内存地址就丢失了,那么在程序中也就无法再引用到它所指向的那块内存了。解决办法有两种:一个是将这个指针变量定义为视类的成员变量,二是在CTestDlg类中重载PostNcDestroy虚函数,释放this指针指向的内存。 void CTestDlg::PostNcDestroy() { delete this; CDialog::PostNcDestroy(); } 点击OK按钮,无论是模态对话框还是非模态对话框,对话框均会消失。模态对话框将对话框的窗口对象销毁了;而非模态对话框窗口对象并未销毁,而是隐藏了。由于基类的OnOk函数会调用EndDialog函数,这个函数用于终止模态对话框,而隐藏非模态对话框,但不销毁。因此,对于非模态对话框来说,如果有一个ID为IDOK的按钮,就必须重写OnOk这个虚函数,并在重写的函数调用DestroyWindow函数,以完成销毁对话框的操作,同时注意不要调用基类的OnOk函数。同理对IDCANCEL也是如此。 Windows消息分为三类:标准消息、命令消息和通告消息。像按钮的单击、列表框的选择这类消息都属于通告消息。 创建一个按钮的方法: 1.void CTestDlg::OnBnClickedBtnAdd(){ // TODO: 在此添加控件通知处理程序代码 // 可以定义一个static BOOL m_bIsCreated = FALSE; if(m_bIsCreated){ m_btn.Create("New",BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD ,CRect(0,0,100,100),this,123); m_bIsCreated = true; } else{ m_btn.DestroyWindow(); m_bIsCreated = false; } } 2.void CTestDlg::OnBnClickedBtnAdd(){ if(!m_btn.m_hWnd){ m_btn.Create("New",BS_DEFPUSHBUTTON|WS_VISIBLE|WS_CHILD,CRect (0,0,100,100),this,123); } else{ m_btn.DestroyWindow(); } } 控件的访问:呵呵,ctrl+已有控件->拖动复制控件 静态文本控件在没人情况下是不发送通告消息的。为了使一个静态文本空间能够响应鼠标单击消息,那么需要进行两个特殊的步骤:一是改变其ID,二是修改其属性对话框中Notify选项。 GetDlgItem函数返回一个有参数ID指定的控件或窗口对象的指针。 CString str; if(IDC_NUMBER1)->GetWindowText(str),str == "Number1"){ //这里注意逗号表达式的使用 GetDlgItem(IDC_NUMBER1)->SetWindowText("数值一"); } else{ GetDlgItem(IDC_NUMBER1)->SetWindowText("Number1"); } 下面我将介绍:在前两个编辑框中输入数字,点Add按钮求和放入第三个编辑框中的七种方法,各个函数的具体参数参见MSDN。 1.GetDlgItem()->Get(Set)WindowText() int num1,num2,num3; char ch1[10],ch2[10],ch3[10]; GetDlgItem(IDC_EDIT1)->GetWindowText(ch1,10); GetDlgItem(IDC_EDIT2)->GetWindowText(ch2,10); num1 = atoi(ch1); num2 = atoi(ch2); num3 = num1 + num2; itoa(num3,ch3,10); //数字10表示十进制 GetDlgItem(IDC_EDIT3)->SetWindowText(ch3); 2.GetDlgItemText()/SetDlgItemText() int num1,num2,num3; char ch1[10],ch2[10],ch3[10]; GetDlgItemText(IDC_EDIT1,ch1,10); GetDlgItemText(IDC_EDIT2,ch2,10); num1 = atoi(ch1); num2 = atoi(ch2); num3 = num1 + num2; itoa(num3,ch3,10); //数字10表示十进制 SetDlgItemText(IDC_EDIT3,ch3); 3.GetDlgItemInt()/SetDlgItemInt() int num1,num2,num3; num1 = GetDlgItemInt(IDC_EDIT1); num2 = GetDlgItemInt(IDC_EDIT2); num3 = num1 + num2; SetDlgItemInt(IDC_EDIT3,num3); 4.将控件和整形变量相关联 每一个控件与一个整形变量相关联,这个还需要在DoDataExchange函数内部实现对话框控件和类成员变量的关联。 void CTestDlg::DoDataExchange(CDataExchange* pDX){ CDialog::DoDataExchange(pDX); DDX_Control(pDX, IDC_BTN_ADD, m_btn); DDX_Text(pDX,IDC_EDIT1,m_num1); DDX_Text(pDX,IDC_EDIT2,m_num2); DDX_Text(pDX,IDC_EDIT3,m_num3); DDV_MinMaxInt(pDX, m_num1, 0, 100); DDV_MinMaxInt(pDX, m_num2, 0, 100); } MFC提供多种以DDX_为前缀的函数,这些函数分别用于不同控件的数据交换;同样提供以DDV_为前缀的数据校验函数。但是在程序代码中不调用DoDataExchange实现数据交换,而是由Cwnd的成员函数UpdateData来调用。DDX(Dialog Data Exchange),DDV(Dialog Data Validation) BOOL UpdateData(BOOL bSaveAndValidate = TRUE); 如果其参数为TRUE,则说明函数正在获取对话框上的控件;如果值为FALSE,则说明该函数正在初始化对话框中的控件,其默认值为TRUE。 UpdateData(); m_num3 = m_num1 + m_num2; UpdateData(FALSE); 5.将控件和控件变量相关联 CEdit m_edit1; CEdit m_edit2; CEdit m_edit3; DDX_Control(pDX, IDC_EDIT1, m_edit1); DDX_Control(pDX, IDC_EDIT2, m_edit2); DDX_Control(pDX, IDC_EDIT3, m_edit3); int num1,num2,num3; char ch1[10],ch2[10],ch3[10]; m_edit1.GetWindowText(ch1,10); m_edit2.GetWindowText(ch2,10); num1 = atoi(ch1); num2 = atoi(ch2); num3 = num1 + num2; m_edit3.SetWindowText(ch3); 6.SendMessage() Windows程序都是基于消息的系统,为了获取或设置窗口的文本,只需要获取或设置创建欧的文本信息,就可以用SendMessage来发送这条消息,从而获取或设置窗口的文本。在Windows系统中,获取窗口文本的消息是WM_GETTEXT,发送该消息以后,系统将把指定窗口的文本复制到调用者提供的一个缓存中。在这个消息的附加参数中,wParam制定复制的字符数,lParam是调用者提供的用来保存窗口文本的缓存地址。而设置窗口的文本的消息是WM_SETTEXT,这个消息的wParam参数没有用,值为0,lParam参数制定了用来设置窗口文本的字符串地址。 int num1,num2,num3; char ch1[10],ch2[10],ch3[10]; //可以采用2种方式来获得窗口句柄,编辑框也是窗口,也有有一个公共句柄成员变量m_hWnd ::SendMessage(GetDlgItem(IDC_EDIT1)->m_hWnd,WM_GETTEXT,10,(LPARAM)ch1); ::SendMessage(m_edit2.m_hWnd,WM_GETTEXT,10,(LPARAM)ch2); num1 = atoi(ch1); num2 = atoi(ch2); num3 = num1 + num2; itoa(num3,ch3,10); m_edit3.SendMessage(WM_SETTEXT,0,(LPARAM)ch3); //最后一个参数需要强制类型转换 7.SendDlgItemMessage() 当发送的消息为WM_GETTEXT和WM_SETTEXT时 int num1,num2,num3; char ch1[10],ch2[10],ch3[10]; SendDlgItemMessage(IDC_EDIT1,WM_GETTEXT,10,(LPARAM)ch1);//直接给对话框的子控件发送消息 SendDlgItemMessage(IDC_EDIT2,WM_GETTEXT,10,(LPARAM)ch2); num1 = atoi(ch1); num2 = atoi(ch2); num3 = num1 + num2; itoa(num3,ch3,10); SendDlgItemMessage(IDC_EDIT3,WM_SETTEXT,0,(LPARAM)ch3); 当发送的消息为EM_GETSL和EM_SETSL时 EM_GETSL获得编辑框复选的内容,EM_SETSL设置编辑框控件中的复选内容。 注:EM打头的消息指的是编辑控件消息(Edit Control Message),wParam参数将接收复选内容的开始位置,lParam参数将接收复选内容的结束位置。这2个参数都要求指向DWORD类型的指针。 SendDlgItemMessage(IDC_EDIT3,EM_SETSEL,1,3); SendDlgItemMessage(IDC_EDIT3,EM_SETSEL,0,-1); //编辑框控件中的所有内容都将被复选 m_edit3.SetFocus();
|