首页 > 代码库 > C++MFC编程笔记day08 MFC对话框的使用

C++MFC编程笔记day08 MFC对话框的使用

一 MFC对话框
   1 分类
   模式和非模式
   2 相关类
   CDialog类-父类是CWnd,本质上是一个窗口,对话框类的父类。
   CCommonDialog类以及子类-通用对话框,颜色对话框、文件对话框、
             查找替换对话框、字体设置对话框、打印设置对话框和
             打印对话框。
   CPropertyPage类-属性页对话框。
   3 在Win32向导中,使用MFC的类创建对话框程序
     3.1 模式对话框
         3.1.1 创建和显示对话框
               CDialog::DoModal()
         3.1.2 对话框的关闭(无需用户处理)
               CDialog::OnOK/OnCancel


     3.2 非模式对话框
         3.2.1 创建和显示对话框
               类似于一般窗口的创建过程
         3.2.2 对话框的关闭
               1 重写CDialog::OnOK/OnCancel函数,在函数中:
                 DestroyWindow()
               2 重写CWnd::PostNcDestroy函数,在函数中:
                 delete this;
     3.3 创建单文档程序,使用菜单分别打开模式/非模式对话框
         对比运行时的效果
     3.4 跟踪DoModal()函数的执行过程
         3.4.1 查找和加载对话框资源
         3.4.2 将父窗口设置为不可用状态
         3.4.3 创建对话框
         3.4.4 进入对话框的消息循环
         3.4.5 当点击OK或则Cancel按钮后,退出循环
         3.4.6 隐藏了对话框窗口,将父窗口设置为可用状态
         3.4.7 销毁对话框
         3.4.8 释放对话框资源
         3.4.9 返回DoModal()函数的返回值
示例:
新建win32 应用程序 ,然后改为支持MFC,并手动创建代码:
// DlgApp.cpp : Defines the entry point for the application.
//


#include "stdafx.h"//#include <afxwin.h>
#include "resource.h"
class CMyDlg:public CDialog
{
public:
CMyDlg():CDialog(IDD_DIALOG1){}//关联对话框资源ID
//以下3函数,使用非模式对话框时要重写实现
virtual void PostNcDestroy( );
virtual void OnOK( );
virtual void OnCancel();
};
void CMyDlg::OnOK()
{
CDialog::OnOK();
DestroyWindow();
}
void CMyDlg::OnCancel()
{
CDialog::OnCancel();
DestroyWindow();
}
void CMyDlg::PostNcDestroy()
{
CWnd::PostNcDestroy();
delete this;
}
class CDlgApp:public CWinApp
{
public:
virtual BOOL InitInstance();
};
CDlgApp theApp;
BOOL CDlgApp::InitInstance()
{
/*  模式对话框
CMyDlg dlg;
m_pMainWnd=&dlg;
dlg.DoModal();//创建和显示模式对话框
*/
//非模式对话框
CMyDlg *pDlg=new CMyDlg;
pDlg->Create(IDD_DIALOG1);//对话框资源ID
m_pMainWnd=pDlg;
pDlg->ShowWindow(SW_SHOW);
return TRUE;
}








二 对话框的数据交换技术(DDX)
   引入它的目的是方便操作控件和获取/设置控件的值
   可以将控件与对话框的成员变量绑定,通过操作对话框的成员变量来
   达到操作控件的目的。
   1 相关函数
     1.1 一系列的绑定函数
         DDX_Control ,绑定控件类型的变量
         DDX_Text    ,绑定值类型的变量
         例如,对话框中有一个编辑框控件,ID,ID_EDIT1
         对话框类中的变量,CString m_strText;//值类型的变量
                          int m_nText;//值类型的变量


                          CEdit m_wndText;//控件类型的变量
     1.2 对话框数据交换函数,包含1.1绑定函数
         CWnd::DoDataExchange
     1.3 当值类型(CString)成员变量与控件之间有数据交换时,调用以下函数:
         UpdateData()
         UpdateData(TRUE)-控件的值传递给成员变量
         UpdateData(FALSE)-成员变量的值放到控件上显示
    2 使用
    3 原理
      3.1 DDX_Control-控件类型的绑定函数
          DDX_Control(CDataExchange* pDX, ...)
          {
             //1根据控件的ID,得到控件的句柄
             HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
             //2 将控件类型的变量与控件的句柄建立映射关系
             rControl.SubclassWindow(hWndCtrl)
             {
               Attach(hWndCtrl);
             }
          }
      3.2 DDX_Text-值类型的绑定函数
          DDX_Text(CDataExchange* pDX, int nIDC,...)
          {
              //1根据控件的ID,得到控件的句柄
             HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
             //2 变量与控件相互赋值
             if (pDX->m_bSaveAndValidate)
    {
int nLen = ::GetWindowTextLength(hWndCtrl);
::GetWindowText(hWndCtrl, value.GetBufferSetLength(nLen), nLen+1);
value.ReleaseBuffer();
     }
     else
     {
AfxSetWindowText(hWndCtrl, value);
     }


          }
      4 函数的调用关系,为什么我们会在CMyDlg::OnInitDialog(),首先
        调用它的父类CDialog::OnInitDialog()?
        只有调用CDialog::OnInitDialog(),对话框显示前,才能将
        控件与变量绑定。具体的调用关系:
        CDialog::OnInitDialog()
        {
           UpdateData(FALSE);
           {
             DoDataExchange(pDx);
             {
               DDX_Control();
               DDX_Text();
             }
           }
        }


示例,建立win32 应用程序,然后手动改为支持MFC,再写代码:
// DlgDDX.cpp : Defines the entry point for the application.
//


#include "stdafx.h"//#include <afxwin.h>
#include "resource.h"
class CMyDlg:public CDialog
{
public:
CMyDlg():CDialog(IDD_DIALOG1){}//关联对话框资源ID
//以下3函数,非模式对话框时要重写实现
virtual void PostNcDestroy( );
virtual void OnOK( );
virtual void OnCancel();
virtual BOOL OnInitDialog();
virtual void DoDataExchange(CDataExchange* pDX);
CButton m_wndOK;//与ok按钮绑定的控件
CString m_wndEdit1;
};
void CMyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX,IDOK,m_wndOK);//界面上控件与成员变量绑定
DDX_Text(pDX,IDC_EDIT1,m_wndEdit1);
}
void CMyDlg::OnOK()
{
UpdateData(TRUE);
AfxMessageBox(m_wndEdit1);
//CDialog::OnOK();
//DestroyWindow();
}
void CMyDlg::OnCancel()
{
CDialog::OnCancel();
DestroyWindow();
}
void CMyDlg::PostNcDestroy()
{
CWnd::PostNcDestroy();
delete this;
}
//对话框初始化
BOOL CMyDlg::OnInitDialog()
{
if(!CDialog::OnInitDialog())
{
return FALSE;
}
CWnd* pbtn = GetDlgItem(IDCANCEL);//获取控件
pbtn->EnableWindow(FALSE);//设置为不可用


m_wndOK.MoveWindow(0,0,100,100,TRUE);//操作绑定的成员变量等于操作控件
m_wndOK.SetWindowText("DDX_OK");
m_wndEdit1="123";
UpdateData(FALSE);
return TRUE;
}
class CDlgApp:public CWinApp
{
public:
virtual BOOL InitInstance();
};
CDlgApp theApp;
BOOL CDlgApp::InitInstance()
{
///*  模式对话框
CMyDlg dlg;
m_pMainWnd=&dlg;
dlg.DoModal();//创建和显示模式对话框
//*/


return TRUE;
}




三 实现登录功能
在主窗口显示前,设置登陆对话框,登陆通过了,才显示主窗口:
CDialogLogin dlglogin;
if(IDOK!=dlglogin.DoModal()) return false;
添加控件与值绑定:
Ctrl+w ,选择 member variables 选项卡,添加与控件对应的变量。
登陆对话框处理:
void CDialogLogin::OnOK()
{
UpdateData(TRUE);//更新控件值到变量中
if(m_UserName=="123" && m_UserPwd=="123")//模拟登陆
{
CDialog::OnOK();
}
else
{
AfxMessageBox("用户名或密码错误!");
}
}


示例:
1、创建MFC对话框应用程序

2、添加对话框,ID为IDD_DIALOG_LOGIN,并修改界面控件。


3、双击对话框标题,选择Create a new class,添加对应的类,类名为 CDialogLogin。


4、ctrl+w添加成员绑定:


5、在app的IninInstance函数中,加入代码:
CDialogLogin dlglogin;
if(IDOK!=dlglogin.DoModal()) return false;
意思是,如果登陆框没有返回IDOK就不显示主框架窗口。


添加点击确定按钮时的消息映射:






//CDialogLogin中实现点击登陆的代码:
void CDialogLogin::OnOK()
{
UpdateData(TRUE);
if(m_UserName=="123" && m_UserPwd=="123")//模拟登陆
{
CDialog::OnOK();//默认关闭对话框,返回IDOK
}
else
{
AfxMessageBox("用户名或密码错误!");
}

}