总结对话框控件访问的七种方式
一、GetDlgItem()->Get(Set)WindowText(ch3);
二、GetWindowText()/SetDlgItemText();
三、GetDlgItemInt()/SetDlgItemInt();
四、将控件和整形变量相关联;
五、将控件和控件变量相关联;
六、SendMessage();
七、SenDlgItemMessage();
一、准备工作:
(一)新建一个MFC AppWizard(exe)工程,名称为“Mybole”,“OK”,选择一个“Single document”,完成。
(二)程序中,要创建一个对话框架,可以通过插入一个资源来完成,选择Insert->Resource(Ctrl+R),在窗口中选择
“Dialog”,然后“New”;也可以通过工具栏上的按钮“New Dialog(Ctrl+1)”,就会出现一个对话框资源,它的ID是
“IDD_DIALOG1”。
(三)在MFC编程当中,对资源的操作,通常都是通过一个和资源相对应的一个类来完成的。对话框的资源也有一个相应的类。
这个类叫CDialog,它是从CWnd类派生出来的。CDialog类,它是一个基类,主要是用来在屏幕上显示一个对话框。对话框有两类:模
态对话框和非模态对话框。模态对话框在应用程序能够继续运行之前必须关闭。非模态对话框允许用户执行另外的操作而不必取消
或删除该对话框。
(四)既然对资源的操作,通常都是通过一个和资源相对应的一个类来完成的,接下来我们要创建一个类,让它和我们的对话
框资源相关联。
1.可以选择“View->ClassWizard”,这时会弹出一个提示对话框“Adding a Class”,提示创建一个新的类,也可以选择一个
现存的类,当然这里我们选择“Create a new class”,“OK”。
2.也可以在对话框资源上双击一下鼠标左键(推荐方法),它也会弹出一个提示对话框“Adding a Class”,提示创建一个新
的类,也可以选择一个现存的类,当然这里我们选择“Create a new class”,“OK”。接下来给新的类起一个名称“CTestDlg”
,程序会自动帮我们选择一个基类“CDialog”,ID号就是“IDD_DIALOG1”。完成“OK”。
(五)这样,在类查看栏中,可以看到新建了一个类,在这个新建的类中,有两个方法:
1.一个是它的构造函数
CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTestDlg::IDD, pParent)
{
}
在这个CTestDlg函数当中,它调用基类CDialog的构造函数,传递CTestDlg当中的IDD成员,这个IDD成员是一个什么样的值
呢,我们可以看一下CTestDlg的头文件“enum { IDD = IDD_DIALOG1 };”,可以看到这个IDD就是我们刚才所插入的资源的ID号
“IDD_DIALOG1”。
2.另外还有一个函数
void CTestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
这个函数主要是用来完成对话框数据的交换,和对话框数据的校验的。
(六)现在,我们有了一个类,并和对话框资源关联起来了。接下来,就要创建一个对话框资源的窗口。点“属性”,可以在
菜单项中增加一个菜单项,取消Pop-up,起一个ID号为“IDM_DIALOG”,名称叫“对话框”,然后在菜单项上点右键,选择
“ClassWizard”,然后在object IDs中找到“IDM_DIALOG”,放到view类完成:在CLass name中选择“CMyboleView”,然后在
Messages中选择“COMMAND”,然后“Add Function...”,“OK”,然后“Edit Code”。然后自动跳转到代码编辑窗口中。
(七)首先看一下模态对话框的创建。
1.创建模态对话框,可以用CDialog类中的一下成员函数DoModal
CDialog::DoModal
virtual int DoModal();
返回值:
整数值,指定了传递给CDialog::EndDialog 的nResult参数值。该函数EndDialog用于关闭对话框。如果函数不能创建对话框,
则返回-1;如果出现其它错误,则返回IDABORT。
说明:
调用该成员函数使用模态对话框并返回对话框结果。当对话框处于活动状态时,该函数处理与用户的交互。这使得对话框是模
态的,使用户在关闭对话框之前不能与其它窗口交互。
如果用户单击了对话框中的按钮,如OK或Cancel,那么消息处理函数如OnOK或OnCancel被调用,从而关闭对话框。缺省的OnOK
成员函数会对对话框数据进行有效性检验和更新,并关闭它得到结果IDOK。缺省OnCancel函数关闭对话框得到结果IDCANCEL,而不
对对话框数据检验或更新,可以覆盖这些消息函数并改变它们的行为。 注意 目前PreTransMessage被调用来处理模态对话框的
消息。
代码如下:
CTestDlg dlg;//先建立一个CTestDlg对象dlg
dlg.DoModal();//然后利用这个对象dlg来调用DoModal来产生一个模态对话框并显示它
在VIEW类中,不知道CTestDlg是一个什么样的类型,所以在MyboleView.cpp中要包含CTestDlg所以的头文件
#include "TestDlg.h"
然后编译一下运行,点击菜单中的对话框,就会出现一个模态对话框,不关掉,程序就不会继续执行。
2.创建一个非查模态对话框,可以用成员函数CDialog::Create
CDialog::Create
BOOL Create(LPCSTR lpszTemplateName, CWnd* pParentWnd = NULL);
BOOL Create(UNIT nIDTemplate, CWnd* pParentWnd = NULL);
返回值:
如果对话框创建和初始化成功,则返回非零值,否则为0。
参数: lpszTemplateName 包含一个对话框模板资源的空终止字符串。
pParentWnd 指向含有对话框的父窗口对象的指针。如果为NULL,对话框对象的父窗口设置为应用的主窗口。
nIDTemplate 包含对话框模板资源的ID数。
说明:
调用Create,使用资源中对话框模板来创建非模态对话框。可将调用置于构造程序内部或者在构造程序启动之后调用。
Create成员函数为访问对话框模板资源提供了两种方法,既可以通过模板名称,也可以模板ID号(如IDD_DIALOG1)。
每种访问方法都会给父窗口传递一个指针。如果pParentWnd为NULL,则应用的主窗口作为其父窗口或所有者窗口来进行创建。
当创建对话框后,Create成员函数应立即返回。
在父窗口中创建之后,如果要求对话框出现,则使用模板中的WS_VISIBLE风格。否则,必须调用ShowWindow。其它对话框风格及应
用,请参阅联机文档“Win32 SDK”中的DIGTEMPLATE结构和“Microsoft Visual C++ 6.0 MFC类库参考手册(二)”中的“Windows
风格”。使用CWnd::DestroyWindow函数来删除由Create函数创建的对话框。
请参阅: CDialog::CDialog, CWnd::DestroyWindow, CDialog::InitModalIndirect, CDialog::DoModal,::CreateDialog
代码如下:
CTestDlg dlg;//先建立一个CTestDlg对象dlg
dlg.Create(IDD_DIALOG1,this);//然后利用这个对象dlg来调用Create来产生一个非模态对话框,第一个参数是ID号,第
二个参数是父窗口C++对象的指针,我们用VIEW类作为它的父窗口,选择this。
dlg.ShowWindows(SW_SHOW);//接下来,还要调用ShowWindows来显示窗口(模态对话框不需要这一步)
编译一下,再运行。这时候,程序并没有显示出我们需要的对话框。为什么?主要是因为,在这里,我们定义的是一个局部变
量CTestDlg dlg,当程序运行完这个函数以后,dlg的生命周期到了,程序就会被销毁,所以见不到窗口。模态对话框为什么就可以
呢?因为模态对话框运行到这里会暂停,所以它可以显示出窗体。
这里可以用两种方法来解决:
一种是将dlg定义成View的成员变量,一种方式是定义成一个指针,在堆上分配一个内存。我们知道,在堆上分配一个内存,它
是和程序整个的生命周期是一致的。这里我们用第二种方法,定义一个指针。将它改成
CTestDlg *pDlg=new CTestDlg();
pDlg->Create(IDD_DIALOG1,this);//它是指针了,所以要用指向操作符。
pDlg->ShowWindows(SW_SHOW);
再编译运行一下。成功。注意一下,当这个窗口出现的时候,我们是可以点击其它的菜单项,因为这个对话框是非模态对话框
。当然这里面有一个问题,我们定义的CTestDlg *pDlg本身是一个局部变量,当它的生命周期结束的时候,它所保存的内存地址就
丢失了,它所指向的这块内存,我们也就没有办法再引用到了。我们可以将它变成一个成员变量,然后在析构函数当中用Delet去释
放这个指针所指向的内存,这是一个需要注意的地方。另外,对于非模态对话框,当我们点击OK的时候,这个窗口并没有被销毁,
其实是被隐藏了,因为它是调用的OnOK虚函数:
CDialog::OnOK
virtual void OnOK();
说明:
当用户按OK按钮(ID是IDOK)时调用。覆盖该函数执行OK按钮动作。如果对话框包括自动数据检验和交换,缺省方式是对应用
的某些变量进行数据的检验和更新。
如果在非模态对话框中实现OK按钮,必须覆盖OnOK成员函数,并在其中调用DestoryWindow。不要调用基类成员函数,那将会调用
EndDialog,它是用来关闭模态对话框的,这只是让对话框不可见,但没有销毁它。
这里我们使用的还是模态对话框,因为非模态对话框使用起来比较麻烦。
二、建立完成一个模态对话框,并在上面拖放添加一个按钮,将它的ID号改为“IDC_BTN_ADD”,Caption改为“Add”。
(一)我们要完成一个功能,当点击Add按钮的时候,在对话框窗口中动态创建一个按钮。
要完成这个功能,就必须在Add按钮上响应一个鼠标单击事件,可以在按钮上右击选择ClssWizard,为它添加一个BN_CLICKED的
消息。按钮单击,属于一种通告消息(消息分为三类:标准消息、命令消息和通告消息),象按钮单击、列表框的选择,都属于通
告消息。增加一个函数,选用默认的函数名,OK。编辑代码。
1.先定义一个BUTTON对象。
因为这个对象是在CTestDlg中完成的,可以在CTestDlg类上点击右键,Add Member Variable,类型填入:CButton,名称填入
:m_btn,并将它选择成私有的Private,OK。
接下来可以利用Create函数来创建一个按钮
m_btn.Create("按键的名称",BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD,
CRect(0,0,100,100),this,123);
编译它,成功。但是第二次点Add按钮时,程序会出现非法操作,这是因为它重复创建了按钮,应该改为创建前检查是否存在。
修改方法,在CTestDlg类上点击右键,再创建一个成员变量,类型为BOOL,名称为“m_blsCreate”,同样将它列入Private,
OK。在
CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTestDlg::IDD, pParent)
{
m_blsCreate=FALSE;
}
中,将这个变量初始化为FALSE。然后在函数里判断一下:
if(m_bliCreate==FALSE)
{
m_btn.Create("按键的名称",BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD,
CRect(0,0,100,100),this,123);
m_blsCreate=TRUE;
}
else //否则就销毁它。
{
m_btn.DestroyWindow();
m_blsCreate=FALSE;
}
再编译一下。当我们第一次点击时,按钮创建了,再次点击,销毁了。这是通过一个变量来创建它。
(二)能否通过一个局部变量来创建它呢?
比如
BOOL blsCreate=FALSE;
if(bliCreate==FALSE)
{
m_btn.Create("按键的名称",BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD,
CRect(0,0,100,100),this,123);
blsCreate=TRUE;
}
else //否则就销毁它。
{
m_btn.DestroyWindow();
blsCreate=FALSE;
}
其实这样是不行的,因为blsCreate是一个局部变量,程序每次执行这个void CTestDlg::OnBtnAdd()函数时,都会将
blsCreate=FALSE,if(bliCreate==FALSE)永远都是成立的,如何来解决这个问题呢,就是将blsCreate局部变量定义成静态的:
static BOOL blsCreate=FALSE;
作为一个静态变量,第一次完成初始化后,以后再执行,程序就不会重新构造了。修改如下:
static BOOL blsCreate=FALSE;
if(bliCreate==FALSE)
{
m_btn.Create("按键的名称",BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD,
CRect(0,0,100,100),this,123);
blsCreate=TRUE;
}
else //否则就销毁它。
{
m_btn.DestroyWindow();
blsCreate=FALSE;
}
编译一下,OK了。
(三)最简单的办法。我们知道,对于一个从CWnd派生出的类来说,其内部都有一个成员变量m_hWnd,保存了和这个C++对象相关
的一个窗口的句柄,当一个对象和窗口相关联的时候,这个句柄就有值了。当这个对象没有和任何一个窗口相关联的时候,这个句
柄是空的,所以可以判断这个句柄是否为空。代码如下:
if(!m_btn.m_hWnd)//这是最简单,最直接的一种方式创建.
{
m_btn.Create("按键的名称",BS_DEFPUSHBUTTON | WS_VISIBLE | WS_CHILD,
CRect(0,0,100,100),this,123);
}else
{
m_btn.DestroyWindow();
}
(第3课结束)
/* //第2种
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);
GetDlgItem(IDC_EDIT3)->SetWindowText(ch3);
*/
/*//第3种
int num1,num2,num3;
num1=GetDlgItemInt(IDC_EDIT1);
num2=GetDlgItemInt(IDC_EDIT2);
num3=num1+num2;
SetDlgItemInt(IDC_EDIT3,num3);
*/
/*//第4种方法-将控件和整形变量相关联;
UpdateData();
m_num3=m_num1+m_num2;
UpdateData(FALSE);
*/
/* 第5种
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;
itoa(num3,ch3,10);
m_edit3.SetWindowText(ch3);
*/
/*
int num1,num2,num3;//第6种访问控件的方式
char ch1[10],ch2[10],ch3[10];
//::SendMessage(GetDlgItem(IDC_EDIT1)->m_hWnd,WM_GETTEXT,10(LPARAM)ch1);//第一种方法发送消息.
//::SendMessage(m_edit1.m_hWnd,WM_GETTEXT,10,(LPARAM)ch1);//第二种方法发送消息.
//GetDlgItem(IDC_EDIT1)->SendMessage(WM_GETTEXT,10,(LPARAM)ch1);//第三种方法发送消息.
m_edit1.SendMessage(WM_GETTEXT,10,(LPARAM)ch1);//第四种发送消息的方法,这4种都可以用.
m_edit2.SendMessage(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);
*/
//第七种,直接访问对话框的子控件
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);
SendDlgItemMessage(IDC_EDIT3,EM_SETSEL,0,-1);//复选这个edit
m_edit3.SetFocus();//设焦点
/*对话框控件访问的7种方式
一、GetDlgItem()->Get(Set)WindowText(ch3);
二、GetWindowText()/SetDlgItemText();
三、GetDlgItemInt()/SetDlgItemInt();
四、将控件和整形变量相关联;
五、将控件和控件变量相关联;
六、SendMessage();
七、SenDlgItemMessage();
*/