11.MFC对话框

一、MFC对话框

  1.对话框的分类

    模式和非模式

  2.相关类

    CDialog类 - 父类CWnd类

    CCommonDialog - 父类是CDialog类,称为通用对话框类,包括颜色对话框、文件对话框、字体对话框、

             查找对话框、页面设置对话框、打印对话框。

    CPropertyPage类 - 父类是CDialog类,称为属性页对话框。

  3.CDialog类的使用类

   3.1 创建基于模式对话框的应用程序

    (1)添加对话框资源,与对话框类关联

    (2)在应用程序类的InitInstance函数中创建和显示对话框窗口

       CDialog::DoModal( )

    (3)对话框的关闭

       不要做任何处理,点击OK或关闭的时,会自动调用相关函数

       CDialog::OnOk

       CDialog::OnOk 

   3.2 创建基于非模式对话框的应用程序

    (1)添加对话框资源,与对话框类关联

    (2)窗口的创建和显示与一般的框架窗口类似

    (3)处理对话框的关闭(销毁对话框)

       重写CDialog::OnOk( )和CDialog::OnOk( )函数,在函数中调用DestroyWindow销毁对话框窗口

       重写CWnd::PostNcDestroy( )函数,在函数中完成对象的自我销毁,delete  this;

  相关代码:

#include "stdafx.h"


//2对话框类
class CMyDialog :public CDialog
{
public:
    CMyDialog() : CDialog(IDD_DIALOG1) { }
    virtual void OnOK();
    virtual void OnCancel();
    virtual void PostNcDestroy();
};
void CMyDialog::OnOK() { DestroyWindow(); }
void CMyDialog::OnCancel() { DestroyWindow(); }
void CMyDialog::PostNcDestroy() { delete this; }

//1应用程序类
class CMyWinApp : public CWinApp
{
public:
    virtual BOOL InitInstance();
};

CMyWinApp theApp;

BOOL CMyWinApp::InitInstance()
{    
    //模式对话框
    //CMyDialog dlg;
    //m_pMainWnd = &dlg;
    //dlg.DoModal();    
    
    //非模式对话框
    CMyDialog *pDlg = new CMyDialog;
    pDlg->Create(IDD_DIALOG1);
    m_pMainWnd = pDlg;
    pDlg->ShowWindow(SW_SHOW);
    pDlg->UpdateWindow();

    return TRUE;
}
View Code

  运行结果:

  

  在MFC应用程序中创建对话框,在框架类中添加代码

  相关代码:

#include "DlgModel.h"
#include "DlgModeless.h"
void CMainFrame::OnDlgModel()
{
    //创建和显示模式对话框
    CDlgModel dlg;
    int nRet = dlg.DoModal();
    if (1 == nRet)
    {
        AfxMessageBox(L"用户点击OK按钮");
    }
    if (2 == nRet)
    {
        AfxMessageBox(L"用户点击Cancel按钮");
    }
}
void CMainFrame::OnDlgModeless()
{
    //创建和显示非模式对话框
    CDlgModeless *pDlg = new CDlgModeless;
    pDlg->Create(IDD_DIALOG2);
    pDlg->ShowWindow(SW_SHOW);
    pDlg->UpdateWindow();
    
}
View Code

  运行结果:

  

  

  4. DoModal函数的执行过程

    4.1 查找并加载资源

    4.2 将父窗口设置为不可用状态

    4.3 创建对话框,进入对话框的消息循环

    4.4 点击OK、Cancel或者关闭按钮时,跳出循环,并且隐藏对话框窗口

    4.5 将父窗口设置为可用和活动状态

    4.6 销毁对话框窗口

    4.7 释放对话框资源

    4.8 返回

    dlg.DoModal( )

    {      

      //1 查找加载资源

      HRSRC hResource  =  ::FindResource( hInst, m_lpszTemplateName,   RT_DIALOG );

      hDialogTemplate  =  LoadResource( hInst,  hResource );

      //2 将父窗口设置为不可用状态

      HWND hWndParent  =  PreModal( );

      ::EnableWindow( hWndParent, FALSE );

      //3 创建对话框,进入对话框的消息循环

      CreateRunDlgIndirect( lpDialogTemplate,  CWnd::FromHandle(hWndParent), hInst )

      {

        BOOL  bRet  =  CreateDlgIndirect( lpDialogTemplate,  pParentWnd,  hInst )

        {

          RunModalLoop( dwFlags ) ==  m_nModalResult; 

          //4 点击OK、Cancel或者关闭按钮时,跳出循环,并且隐藏对话框窗口      

          SetWindowPos( NULL, 0, 0, 0, 0,  SWP_HIDEWINDOW |

            SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );

        }

      }

      //5 将父窗口设置为可用和活动状态

      ::EnableWindow( hWndParent,  TRUE );

      ::SetActiveWindow( hWndParent );

      //6 销毁对话框窗口

      DestroyWindow( );

      //7 释放对话框资源

      FreeResource( hDialogTemplate );

      return  m_nModalResult;

    }     

二、控件操作

  1. 控件的初始化放到对话框的OnInitDialog( )函数中

  2. 对话框数据交换技术DoDataExchange,DDX

    2.1概念

      将控件与对话框类的成员变量绑定,通过操作成员变量的方式间接的操作控件

    2.2 使用步骤

      (1)添加成员变量

      (2)在CWnd::DoDataExchange( )函数中,将变量与控件绑定

         DDX_Control( ) - 控件类型的绑定

         DDX_Text( ) - 值类型的绑定,需要结合UpdateData使用

      (3)UpdateData(BOOL)函数

         FALSE - 将变量的值传递给控件

         TRUE - 用户在控件中输入的值传递给变量

  相关代码:  

#include "stdafx.h"


class CMyDialog : public CDialog
{
public:
    CMyDialog() : CDialog(IDD_DIALOG1) { }
    virtual BOOL OnInitDialog();
    virtual void DoDataExchange(CDataExchange* pDX);
    virtual void OnOK();
protected:
    CButton m_btnOK;//与OK按钮绑定的成员变量
    CString m_sText;//与文本框绑定的值类型的成员变量
};
void CMyDialog::OnOK()
{
    UpdateData(TRUE);//将用户在控件中输入的值传递给变量
    AfxMessageBox(m_sText);
    CDialog::OnOK();
}
void CMyDialog::DoDataExchange(CDataExchange* pDX)
{
    //变量m_btnOK与OK按钮绑定
    DDX_Control(pDX, IDOK, m_btnOK);
    //值类型的绑定
    DDX_Text(pDX, IDC_EDIT1, m_sText);
}
BOOL CMyDialog::OnInitDialog()
{
    if (!CDialog::OnInitDialog())
        return FALSE;

    //控件的初始化操作
    CWnd *pWnd = GetDlgItem(IDCANCEL);
    pWnd->EnableWindow(FALSE);

    //使用DDX操作OK按钮
    m_btnOK.MoveWindow(0, 0, 100, 100);
    m_btnOK.SetWindowTextW(L"DDXOK");

    //值类型的操作
    m_sText = "Hello World";
    UpdateData(FALSE);
    return TRUE;
}

class CMyWinApp : public CWinApp
{
public:
    virtual BOOL InitInstance();
};

CMyWinApp theApp;

BOOL CMyWinApp::InitInstance()
{
    CMyDialog dlg;
    m_pMainWnd = &dlg;
    dlg.DoModal();
    return TRUE;
}
View Code

  运行结果:

  

    2.3 实现原理

      (1)控件类型绑定

         DDX_Control( pDX,  IDOK,  m_btnOK )

         {

           //1 根据控件ID获取控件句柄

           pDX->PrepareCtrl( IDOK );  //给pDX中的成员m_pDlgWnd赋值

           HWND  hWndCtrl;

           pDX->m_pDlgWnd->GetDlgItem( IDOK,  &hWndCtrl );

           //2 将控件句柄附加到对象中

           m_btnOK.SubclassWindow( hWndCtrl )

           {

             Attach( hWndCtrl )

             {

               pMap->SetPermanent( m_hWnd = hWndCtrl ,  &m_btnOK )

               {

                 //以控件句柄为键,以变量地址为值,建立映射关系

                 m_permanentMap[ m_hWnd ]  =  &m_btnOK;  //★★★

               }

             }

           }

         }

      (2)值类型的绑定

         UpdateData( TRUE )

         {

           CDataExchange  dx( this, TRUE );  //对话框信息及相关参数

           DoDataExchange( &dx )

           {    

             //回到我们自己写的代码         

             DDX_Text( pDX,  IDC_EDIT1,  m_sText )

             {

               //1 根据控件ID得到控件句柄

               HWND  hWndCtrl  =  pDX->PrepareEditCtrl( IDC_EDIT1 ); 

               //2.1 将用户在控件的输入传递给变量            

               if  ( pDX->m_bSaveAndValidate )  
               {

                  //获得文本框内容长度

                 int nLen  =  ::GetWindowTextLength( hWndCtrl ); 

                 //获取文本框的值

                 ::GetWindowText( hWndCtrl,  m_sText .GetBufferSetLength( nLen ), nLen + 1 );  

               }

                //2.2 将变量的值显示到控件上

               else

               {

                 AfxSetWindowText( hWndCtrl,  m_sText ); 

               }

             }

           }

         }

原文地址:https://www.cnblogs.com/csqtech/p/5727563.html