《MFC那点事儿》の访问对话框控件的方式

来源:互联网 发布:康熙王朝 1080p 源码 编辑:程序博客网 时间:2024/05/16 23:55

获取和设置对话框控件标题或内容的相关方法介绍:

 

0)先来看一个获取窗口中指定控件或子窗口指针的函数CWnd::GetDlgItem

CWnd* GetDlgItem(

   int nID //控件或子窗口的ID

) const;

void GetDlgItem(

   int nID, //控件或子窗口的ID

   HWND* phWnd //指向子窗口的指针

) const;

“返回值”是指向控件或子窗口的指针,如果指定nID控件不存在,返回值是NULL

要注意的是:返回的指针可能是临时的,因此不能存下来以待后面使用。我们通常会将返回的指针转换为nID指向控件的类型。例如:

// uses GetDlgItem to return a pointer to a user interface control

CEdit* pBoxOne;

pBoxOne = (CEdit*)GetDlgItem(IDC_ASCEEDIT);

GotoDlgCtrl(pBoxOne);

 

 

1CWnd::GetWindowText函数实现获取CWnd的标题内容,或者当CWnd对象是一个控件时,函数将获取控件中文本内容而不是标题内容;函数原型如下:

int GetWindowText(

   LPTSTR lpszStringBuf, //接收返回的内容的缓冲区

   int nMaxCount //复制到缓冲区的最大字符个数

) const;

void GetWindowText(

   CString& rString //接收返回的内容的CString对象

) const;

第一个函数的返回值是复制的字符个数,不包括null结束符;当CWnd没有标题或标题为空时返回0

该成员函数使得WM_GETTEXT消息发送给CWnd对象。

 

CWnd::SetWindowText函数实现设置CWnd对象的标题内容,而当CWnd对象是一个控件时,函数将设置控件中文本内容,函数原型如下:

void SetWindowText(

   LPCTSTR lpszString

);

 

实例代码如下:

// set the text in IDC_EDITNAME

CWnd* pWnd = GetDlgItem(IDC_EDITNAME);

pWnd->SetWindowText(_T("Gerald Samper"));

 

// Get the text back. CString is convenient, because MFC

// will automatically allocate enough memory to hold the

// text--no matter how large it is.

CString str;

pWnd->GetWindowText(str);

ASSERT(str == _T("Gerald Samper"));

 

// The LPTSTR override works, too, but it might be too short.

// If we supply a buffer that's too small, we'll only get those

// characters that fit.

TCHAR sz[10];

int nRet = pWnd->GetWindowText(sz, 10);

 

// Nine characters, plus terminating null

ASSERT(_tcscmp(sz, _T("Gerald Sa")) == 0);

ASSERT(nRet == 9);

 

// You can query the length of the text without the length of

// the string using CWnd::GetWindowTextLength()

nRet = pWnd->GetWindowTextLength();

ASSERT(nRet == 13);

 

 

2CWnd::GetDlgItemText函数用来返回对话框中指定ID的控件上的文本,也就是说,GetDlgItemText函数将GetDlgItemGetWindowText这两个函数的功能组合起来了:

int GetDlgItemText(

   int nID, //控件的ID

   LPTSTR lpStr, //指向接收控件标题或文本的缓冲区的指针

   int nMaxCount  //复制到缓冲区的最大字符个数

) const;

int GetDlgItemText(

   int nID, //控件ID

   CString& rString  //接收控件标题或文本内容

) const;

 

函数返回值是实际复制到缓冲区的字符个数,不包括null结束符;当没有复制任何东西时,返回0

 

CWnd::SetDlgItemText函数用来设置对话框中指定控件的标题或文本:

void SetDlgItemText(

   int nID, //控件ID

   LPCTSTR lpszString  //要设置的内容

);

该函数将发送一个WM_SETTEXT消息给指定的控件。

 

 

3CWnd::GetDlgItemInt函数用来获取指定控件的文本,并将其转换为一个整型数值:

UINT GetDlgItemInt(

   int nID, //控件ID

   BOOL* lpTrans = NULL, //指向一个布尔型变量,该变量接收转换成功与否标志

   BOOL bSigned = TRUE  //指定被检索的值是否有符号

) const;

返回值是转换后的整型值。该函数将向控件发送一个WM_GETTEXT消息。

 

CWnd::SetDlgItemInt函数用指定的数值来设置指定控件的文本:

void SetDlgItemInt(

   int nID, //控件ID

   UINT nValue, //指定用来产生控件上文本的整型数值

   BOOL bSigned = TRUE  //指定数值是否是有符号数字

);

该函数的调用将发送一个WM_SETTEXT消息给指定的控件。

 

 

4)为了将对话框控件与对话框类成员变量相关联,我们可以使ClassWizard来帮助我们完成(VC6.0VC10.0中有ClassWizard)。首先打开ClassWizard对话框,并单击Member Variable选项卡,在Class name下拉列表框中选择CASCEDlg,这时在Control IDs列表中将列出这个对话框中的所有控件的ID。接着就可以为指定的控件ID关联成员变量,这里选择变量的类别是:Value,变量的类型是int,关联了几个变量后,实例代码如下:

在类的头文件中,可以看到在两个AFX_DATA注释宏之间增加了三个成员变量:

//{{AFX_DATA(CASCEDlg)

enum {  IDD = IDD_DIALOG_ASCE };

int m_num1;

int m_num2;

int m_total;

//}}AFX_DATA

而在CASCEDlg类的构造函数中,可以看到对这三个成员变量进行了初始化:

CASCEDlg::CASCEDlg(CWnd* pParent /*=NULL*/)

         : CDialog(CASCEDlg::IDD, pParent)

{

         //{{AFX_DATA_INIT(CASCEDlg)

         m_num1 = 0;

         m_num2 = 0;

         m_total = 0;

         //}}AFX_DATA_INIT

}

而接着在DoDataExchange函数中完成了对话框数据的交换和校验,在这个函数内部调用了三个DDX_TEXT函数,后者的功能就是将ID指定的控件与特定的类成员变量相关联。因此,在DoDataExchange函数内部实现了对话框控件与类成员变量的关联:

void CASCEDlg::DoDataExchange(CDataExchange* pDX)

{

         CDialog::DoDataExchange(pDX);

         //{{AFX_DATA_MAP(CASCEDlg)

         DDX_Text(pDX, IDC_EDIT1, m_num1);

         DDX_Text(pDX, IDC_EDIT2, m_num2);

         DDX_Text(pDX, IDC_EDIT_TOTAL, m_total);

         //}}AFX_DATA_MAP

}

注:MFC提供了多种DDX_为前缀的函数,这些函数分别用于不同控件的数据交换。

 

这之后,就可以使用这些成员变量了,例如实现m_total是前面两个变量的和:

m_total = m_num1 + m_num2;

但是在代码中仅仅写这一句是实现不了编辑框的赋值的,因为对话框数据交换是由DoDataExchange函数完成的,但在程序代码中从来不能直接调用这个函数,而是通过CWnd::UpdateData来调用。通过后者来初始化对话框控件或从对话框获取数据。即为了是数据生效,需要在代码中调用UpdateData函数:

BOOL UpdateData(

   BOOL bSaveAndValidate = TRUE

);

当参数bSaveAndValidateTRUE时,说明该函数正在获取对话框数据;当为FALSE时,说明该函数正在初始化对话框的控件。因此,实现相加并显示在编辑框中的完整代码是:

UpdateData();

m_total = m_num1 + m_num2;

UpdateData(FALSE);

 

 

5)同样使用ClassWizard,但这次我们将编辑框控件关联到一个控件变量,即代表控件本身。即在选择变量类型时选择Control,此时,变量类型会自动变为CEdit。同样添加三个成员变量,此时头文件代码片段我为:

//{{AFX_DATA(CASCEDlg)

enum {  IDD = IDD_DIALOG_ASCE };

CEdit m_edit1;

CEdit m_edit2;

CEdit m_edit_total;

int m_num1;

int m_num2;

int m_total;

//}}AFX_DATA

 

而在CASCEDlg类的DoDataExchange函数中增加了三个DDX_Control函数,分别将一个对话框控件与一个变量相关联:

void CASCEDlg::DoDataExchange(CDataExchange* pDX)

{

         CDialog::DoDataExchange(pDX);

         //{{AFX_DATA_MAP(CASCEDlg)

         DDX_Control(pDX, IDC_EDIT1, m_edit1);

         DDX_Control(pDX, IDC_EDIT2, m_edit2);

         DDX_Control(pDX, IDC_EDIT_TOTAL, m_edit_total);

         DDX_Text(pDX, IDC_EDIT1, m_num1);

         DDX_Text(pDX, IDC_EDIT2, m_num2);

         DDX_Text(pDX, IDC_EDIT_TOTAL, m_total);

         //}}AFX_DATA_MAP

}

而这些控件变量代表的就是控件本身,并且CEdit类派生于CWnd类,因此,可以利用这些控件变量调用GetWindowTextSetWindowText这两个函数来获取和设置编辑框中的文本。

 

 

6Windows程序都是基于消息的系统,为了获取或设置窗口的文本,只要知道获取或设置窗口文本的消息,就可以通过SendMessage来发送这条消息,从而获取或设置窗口的文本。

Windows系统中,获取窗口文本的消息是WM_GETTEXT,发送该消息后,系统将把指定窗口的文本复制到调用者提供的一个缓存中。在这个消息的两个附加参数中,wParam指定将复制的字符数,lParam就是调用者提供的用来保存窗口文本的缓存地址。

而设置窗口文本的消息是WM_SETTEXT,这个消息的wParam参数没有用到,值为0;而lParam参数指定了用来设置窗口文本的字符串地址。

实例代码如下:

void CASCEDlg::OnBtnAdd()

{

         int num1, num2, numTotal;

         char ch1[10], ch2[10], ch3[10];

         ::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);

         numTotal = num1 + num2;

 

         itoa(numTotal, ch3, 10);

         m_edit_total.SendMessage(WM_SETTEXT, 0, (LPARAM)ch3);

}

 

 

7)直接给对话框中的子控件发送消息,使用函数CWnd::SendDlgItemMessage

LRESULT SendDlgItemMessage(

   int nID, //要接收该消息的对话框中控件的ID

   UINT message, //要发送的消息类型

   WPARAM wParam = 0, //

   LPARAM lParam = 0  //

);

该函数的功能相当于GetDlgItemSendMessage函数的组合。因为SendDlgItemMessage函数本身就是在一个对话框中给它的子控件发送消息时使用的,因此在调用时不必先获得子控件对象,再发送消息,可以直接给子控件发送消息:

void CASCEDlg::OnBtnAdd()

{

         int num1, num2, numTotal;

         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);

         numTotal = num1 + num2;

 

         itao(numTotal, ch3, 10);

         SendDlgItemMessage(IDC_EDIT_TOTAL, WM_SETTEXT, 0, (LPARAM)ch3);

}

 

最后总结上面的七种访问对话框控件的方式:

1GetDlgItem()->Get(Set)WindowText();(常用)

2GetDlgItemText()/SetDlgItemText()

3GetDlgItemInt()/SetDlgItemInt()

4)将控件和非控件变量相关联;(常用)

5)将控件和控件变量相关联;(常用)

6SendMessage()

7SendDlgItemMessage()