第 3章 对话框和常见控件对话框和控件之间是一对密不可分的卵生姐妹。通常来讲,对话框中有一些控件元素,控件通常也建在对话框中。
对话框是一个弹出式的标准窗口。当我们在一个应用程序中需要用户进行数据的输入,或需要与用户进行对话,对话框弹出来让用户从一系列输入操作中进行选择,而每一种操作都对应着一个控件的实现,这些控件由诸如单选按钮、复选按钮、编辑框和列表框等对象组成。
对话框编程我们可以使用对话框函数。使用对话框函数除了待处理消息不同外,在其它方面对话框函数均类似于窗口函数。实际上,对话框的许多函数就是从窗口类派生的。
Windows对话框有两种基本类型:
l 有模式对话框( Model Dialog)
l 无模式对话框 (Modeless Dialog)。
有模式对话框使父窗口操作无效,不允许用户回到父窗口操作。当有模式对话框工作时,对话框消息处理循环从应用队列中直接接收消息传递给对话框函数,WinMain函数收不到消息。与有模式对话框相反,无模式对话框不妨碍父窗口的正常工作,无模式对话框接收 WinMain函数消息循环的输入,它没有自己的消息循环。
标准控件也是一些行为标准化了的窗口,一般用在对话框或其它窗口中充当与用户交互的窗口元素。在 Visual C++中,可以使用的控件分成三类,Windows标准控件,ActiveX控件,
其它 MFC控件类。在本章中我们仅讲述 Windows标准控件。
所讲的内容主要包括各个控件的使用及相应的使用技巧。
有模式对话框对话框是大多数 Windows应用程序的重要的用户界面组件。在 Windows开发中弹出对话框是一种常用的 I/O手段,我们需要将一个自建并编辑好的对话框保存在 Visual C++应用工程的资源文件中。 Visual C++提供了对话框编辑工具,我们利用编辑工具可以方便的添加各种控件到对话框中去,而且利用 ClassWizard可以方便的生成新的对话框类和映射消息。我们可以用对话框资源编辑器创建对话框模板,对话框资源编辑器将编辑的模板以扩展名,res文件保存在对话框模板资源中。
然后基于对话框的模板用 ClassWizard创建一个从 CDialog 类派生的对话框类,最后建立该类对象,建立对话框。
模式对话框实现对话框是一个特殊的窗口,主要用于用户的数据输入。
由于对话框是窗口,所以它和其它窗口一样响应消息。尽管一般窗口处理大量消息,而一般对话框只处理两种消息:
WM_INITDIALOG和 WM_COMMAND。当对话框窗口被创建后,在对话框显示之前,对话框先接收消息 WM_CREATE,
然后响应消息 WM_INITDIALOG。 WM_INITDIALOG消息在对话框窗口创建之后并且已初始化了所有对话框里的控件以后到达。对话框窗口获得 WM_INITDIALOG消息之后将处理派生类中的 OnInitDialog()消息处理函数。在这里我们可以修改控件数据,不过修改控件数据要在对话框显示之前。
MFC 提供类 CDialog作为对话框服务的基类,类 CDialog将对话框模板与使用对话框时必需熟悉的几种类方法进行封装 。 对于对话框中发送消息的的控件,我们可创建相应的消息处理程序 。 MFC编译器提供的框架工具使得我们把对话框中的控件消息映像到派生类的类函数变得简单,快捷 。 对话框数据映像函数使用专门的值初始化对话框中的控件,接着检索数据并使之有效 。 大多数对话框需要类成员变量来跟踪用户的输入,这些数据在数据映像中使用,它们在对话控件与类变量之间自动映像数据 。
为创建对话框,首先建立 CDialog对象,然后创建和显示对话框窗口我们有两种选择:一种方法是调用函数 CDialog::DoModal()来创建有模式对话框窗口,另一种方法是调用函数 CDialog::Create()来创建无模式对话框窗口,
在上述两种情况之下,对话框对象先初始化,然后创建对话框以及它的控件 。
类 CDialog成员函数 Create()使用两种重载原形,最常用的一种如下:
Create(UINT nIDTemplate,CWnd * pParentWnd=NULL);
其中,参数 nIDTemplate是一个对话框模板的标识符,
参数 pParentWnd是对话框所属的父窗口 。
对话框中的数据交换和数据检查
MFC提供两种方法在对话框中进行数据交换和数据检查( Dialog Data
Exchange/Dialog Data Validation),数据交换和数据检查的基本思想是将某一变量和对话框中的一个控件窗口进行关联,然后通过调用 BOOL
UpdateData( BOOL bSaveAndValidate = TRUE )来指示 MFC将变量中数据放入控件窗口还是将控件窗口中数据取到变量中并进行合法性检查。
在进行数据交换时一个控件窗口可以和两种类型的变量相关联,一种是控件( Control)对象,比如说按钮控件窗口可以和一个 CButton对象相关联,这种情况下我们可以通过该对象直接控制控件窗口,当然我们可以使用 GetDlgItem(IDC_CONTROL_ID)来得到窗口对象指针;一种是内容对象,比如说输入框可以和一个 CString对象关联,也可以和一个 UINT类型变量关联,这种情况下我们可以直接设置或获取窗口中的输入内容。
而数据检查是在一个控件窗口和一个内容对象相关联时在存取内容时对内容进行合法性检查,比如说当一个输入框和一个 CString对象关联时,我们可以设置检查 CString的对象的最长 /最小长度,当输入框和一个 UINT变量相关联时我们可以设置检查 UINT变量的最大 /最小值。在 BOOL
UpdateData( BOOL bSaveAndValidate = TRUE )被调用后,
合法性检查会自动进行,如果无法通过检查 MFC会弹出消息框进行提示,并返回 FALSE。
设置 DDX/DDV在 Visual C++中非常简单,ClassWizard
可以替我们完成所有的工作,我们只需要打开 ClassWizard
并选中 Member Variables页,我们可以看到所有可以进行关联的控件窗口 ID列表,双击一个 ID会弹出一个添加变量的对话框,然后填写相关的信息后按下确定按钮就可以了。
然后选中刚才添加的变量在底部的输入框中输入检查条件。
Windows标准控件
MFC 提供了一组与 Microsoft Windows 所提供的标准控件窗口相对应的类。这些类主要有:静态类、按钮类、
编辑控件类、滚动条类、列表框类和组合框类等。每个控件类都封装了一个 Windows控件,并提供了与基本控件之间的成员函数用户接口。使用一个控件对象的成员函数,就可以获取和设置控件的值或状态,并响应由该控件送给其父窗口(通常为一个对话框)的各种标准消息。
控制是 Control 的意译,又叫控件,以下我们对控制和控件不加区分。除了上述标准的 Windows 控制之外,
MFC还提供了以位图作标签的按钮等控制。
静态文本控件静态文本控件的功能比较简单,可作为显示字符串、图标、位图用。创建一个窗口可以使用成员函数:
BOOL CStatic::Create( LPCTSTR lpszText,DWORD dwStyle,const
RECT& rect,CWnd* pParentWnd,UINT nID = 0xffff );
其中,dwStyle将指明该窗口的风格,除了子窗口常用的风格
WS_CHILD,WS_VISIBLE外,我们可以针对静态控件指明专门的风格。
l SS_CENTER,SS_LEFT,SS_RIGHT 指明字符显示的对齐方式。
l SS_GRAYRECT 显示一个灰色的矩形
l SS_NOPREFIX 如果指明该风格,对于字符 &将直接显示,否则
&将作为转义符,&将不显示而在其后的字符将有下划线,如果需要直接显示 &必须使用 &&表示。
l SS_BITMAP 显示位图
l SS_ICON 显示图标
l SS_CENTERIMAGE 图象居中显示利用成员函数 SetWindowText 设置控件显示的文本 GetWindowText 得到控件当前显示的文本,利用成员函数 SetIcon设置控件显示的图标
GetIcon得到控件当前显示的图标,利用成员函数 SetBitmap 设置控件显示的位图,GetBitmap得到控件当前显示的位图。
按钮控件在 MFC类库中,按钮控件使用类 CButton表示,CButton包含了三种样式的按钮:
l 命令按钮( Push Button)
l 复选按钮( Check Box)
l 单选按钮( Radio Box)
所以我们在利用 CButton对象生成按钮窗口时需要指明按钮的风格。
创建按钮的函数原型如下所示:
BOOL CButton::Create( LPCTSTR lpszCaption,
DWORD dwStyle,const RECT& rect,CWnd* pParentWnd,
UINT nID );
编辑框控件编辑框( Edit Box)控件 Edit窗口是用来接收用户输入最常用的一个控件。创建一个输入窗口可以使用成员函数:
BOOL CEdit::Create( LPCTSTR lpszText,DWORD
dwStyle,const RECT& rect,CWnd* pParentWnd,UINT
nID = 0xffff );
滚动条控件滚动条( Scroll Bar)一般不会单独使用,因为 SpinCtrl
可以取代滚动条的一部分作用,但是如果我们需要自己生成派生窗口,滚动条还是会派上一些用场。创建一个滚动条可以使用成员函数:,
BOOL CEdit::Create( LPCTSTR lpszText,DWORD
dwStyle,const RECT& rect,CWnd* pParentWnd,UINT nID
= 0xffff );
列表框列表框( ListBox)窗口用来列出一系列的文本,每条文本占一行。
创建一个列表窗口可以使用成员函数:
BOOL CListBox::Create( LPCTSTR lpszText,DWORD
dwStyle,const RECT& rect,CWnd* pParentWnd,UINT nID =
0xffff );
组合框组合框( Combo Box)窗口是由一个输入框和一个列表框组成的。创建一个组合窗口可以使用成员函数:
BOOL CListBox::Create( LPCTSTR lpszText,DWORD
dwStyle,const RECT& rect,CWnd* pParentWnd,UINT nID
= 0xffff );
树形控件树形控件( TreeCtrl)和下面要讲的列表控件( ListCtrl)
在系统中大量被使用,例如 Windows资源管理器就是一个典型的树形控件例子。
树形控件可以用于树形的结构,其中有一个根接点 (Root)
然后下面有许多子结点,而每个子结点上有允许有一个或多个或没有子结点。 MFC中使用 CTreeCtrl类来封装树形控件的各种操作。通过调用
BOOL Create( DWORD dwStyle,const RECT& rect,
CWnd* pParentWnd,UINT nID );
树形控件树形控件( TreeCtrl)和下面要讲的列表控件( ListCtrl)
在系统中大量被使用,例如 Windows资源管理器就是一个典型的树形控件例子。
树形控件可以用于树形的结构,其中有一个根接点 (Root)
然后下面有许多子结点,而每个子结点上有允许有一个或多个或没有子结点。 MFC中使用 CTreeCtrl类来封装树形控件的各种操作。通过调用
BOOL Create( DWORD dwStyle,const RECT& rect,
CWnd* pParentWnd,UINT nID );
列表控件列表控件( List Ctrl)可以看作是功能增强的 ListBox,
它提供了四种风格,而且可以同时显示一列的多中属性值。 MFC中使用 CListCtrl类来封装列表控件的各种操作。
BOOL Create( DWORD dwStyle,const RECT& rect,
CWnd* pParentWnd,UINT nID );
属性页控件属性页控件( Tab Ctrl)可以在一个窗口中添加不同的页面,然后在页选择发生改变时得到通知。 MFC中使用
CTabCtrl类来封装属性页控件的各种操作。
我们可以通过调用下列函数:
BOOL Create( DWORD dwStyle,const RECT& rect,
CWnd* pParentWnd,UINT nID );
动画控件动画控件是实现多媒体应用的控件,在 MFC的
CAnimateCtrl类中封装了动画控件实现技术,该类的 Create
成员函数可以创建动画控件,其函数说明形式为:
BOOL Create( DWORD dwStyle,const RECT& rect,
CWnd* pParentWnd,UINT nID );
无模式对话框在 Microsoft 基本类库( MFC)中,有模式对话框和无模式对话框都共用一个基类 CDialog,它们都需要对话框资源,而这些都可以使用对话框资源编辑器加以完成。我们已知道有模式对话框通过一个资源模板 ID作为参数的
CDialog 的构造函数来构造一个对话框对象,然后通过调用 DoModal()函数来显示有模式对话框窗口。当 DoModal()函数返回时,对话框窗口就不存在了。
因此,我们可以在栈中创建模式对话框的对象,这样就可以保证当程序控制转到 C++对话框对象所在范围之外时,它能够被及时的删除掉。无模式对话框比有模式对话框要复杂,我们首先要调用 CDialog 的默认构造函数构造一个对话框对象,然后我们通过调用 CDialog::Create 成员函数来创建无模式对话框窗口,这时不能用前面讲的有模式对话框建立窗口函数 DoModal()函数。
Create 用资源 ID作为参数,并且当对话框仍然保留在屏幕上时,控件数据就已经立刻返回了。我们必须考虑何时构造对话框对象、何时创建对话框对象窗口、何时处理对话框中的用户输入数据、何时删除对话框。
无模式对话框在创建后其他窗口还可以继续接收用户的输入,因而无模式对话框也类似一个弹出窗口。创建无模式对话框我们需要调用下列函数:
BOOL CDialog::Create( UINT nIDTemplate,CWnd* pParentWnd = NULL );
创建 之后还需要调用下列函数显示对话框窗口:
BOOL CDialog::ShowWindow( SW_SHOW);否则无模式对话框将是不可见的。
系统对话框及其它对话框在 Windows系统中我们除了可以建立有模式对话框和无模式对话框之外,我们还可以建立其它形式的对话框。有些对话框是系统直接提供的,如通用对话框、
消息框等。有些对话框创建的形式更具有逻辑性、集合性和系统性,如属性对话框。有的对话框就是一个完整的应用程序等。
通用对话框通用对话框是W indows预定义的对话框,我们可以使用通用对话框来执行各种标准人机交互操作,如:文件选择对话框、
颜色选择对话框、字体选择对话框、查找与替换对话框、打印对话框、页面设置对话框。它们都有相应的 MFC库中类来支持。
我们可以使用象 CFileDialog,CColorDialog,CFontDialog、
CFindReplaceDialog,CPageSetupDialog,CPrintDialog类来实现这些通用对话框。 一般来讲,我们不需要再派生新的类,
因为这些基类已经提供了常用的功能。而且在创建并等待对话框结束后我们可以通过成员函数得到用户在对话框中的选择。
所有这些对话框都是从一个公共基类 CCommonDialog派生的。
下面我们逐个介绍这些类有关功能。
CColorDialog颜色选择对话框的使用方法
CColorDialog类封装了标准的“颜色”对话框,使得用户可以从颜色列表中选择要用的颜色。我们编程时可以按以下方法在程序中嵌入“颜色”对话框:
首先我们需要构造一个对象并提供相应的参数,构造函数原型如下:
CColorDialog::CColorDialog( COLORREF clrInit = 0,
DWORD dwFlags = 0,CWnd* pParentWnd = NULL )
CFontDialog字体选择对话框的使用方法
CFontDialog类封装了标准的“字体”对话框,使得用户可以从系统安装的字体列表中选择要用的字体。编程时可以按以下方法在程序中嵌入“字体”对话框:
首先构造一个对象并提供相应的参数,构造函数原型如下:
CFontDialog::CFontDialog( LPLOGFONT lplfInitial =
NULL,DWORD dwFlags = CF_EFFECTS |
CF_SCREENFONTS,CDC* pdcPrinter = NULL,CWnd*
pParentWnd = NULL );
CFindReplaceDialog对话框的使用方法
CFindReplaceDialog类封装了通用的“查找”和“替换”
对话框。对话框仅仅提供了标准接口,它允许输入待查找和替换的字符串,而真正的查找和替换功能则需要编程人员自己实现。与其他通用对话框不同的是,“查找”和“替换”
对话框是无模式的。因此,构造 CFindReplaceDialog对象时要用到 new操作符,如:
CFindReplaceDialog * pFindReplaceDlg = new
CFindReplaceDialog();
CPageSetupDialog对话框的使用方法
CPageSetupDialog类封装了标准的“页面设置”对话框,该类使得用户可以设置和修改打印边距等有关信息。 Windows
程序一般使用“页面设置”对话框来取代“打印设置”对话框,编程时可以按以下方法在程序中嵌入“页面设置”对话框:
首先,我们要构造 CPageSetupDialog对象。构造函数原型如下:
CPageSetupDialog( DWORD dwFlags = PSD_MARGINS |
PSD_INWININIINTLMEASURE,CWnd* pParentWnd =
NULL );
CPrintDialog打印选择对话框的使用方法
CPrintDialog类封装了标准的“打印”和“打印设置”对话框。 AppWizard生成的应用程序框架处理打印时会自动显示这些对话框。如果不想让框架处理,而想通过编程来实现打印时,那么我们就要用到 CPrintDialog类,编程方法如下:
首先,我们构造 CPrintDialog类对象。构造函数原型如下:
CPrintDialog( BOOL bPrintSetupOnly,DWORD
dwFlags = PD_ALLPAGES | PD_USEDEVMODECOPIES |
PD_NOPAGENUMS | PD_HIDEPRINTTOFILE |
PD_NOSELECTION,CWnd* pParentWnd = NULL );
属性表对话框前面我们讲了属性表控件的使用,这里我们介绍基于对话框模板如何创建属性表对话框。属性表( Property Sheet)
对话框又称为选项卡对话框。每个属性表含有一个或多个属性页( Property page)。每个属性页是基于对话框模板创建的,它出现在属性表的某一选项卡中。选项卡命名属性页并指示属性页的用途,单击选项卡即可切换到相应的属性页。
属性页和属性表都可以由对话框资源编辑器以编辑对话框的方式进行编辑,这样给页面界面开发带来了方便。同时使用上也遵守普通对话框的规则,所以学习起来很方便。属性对话框由两部分构成:多个属性页( CPropertyPage)和一个属性表对话框( CPropertySheet)。
子窗口类型的对话框我们在应用程序中可以使用对话框作为子窗口,
这样做可以使界面设计简化而且修改起来更加容易。
简单的说这种技术的关键就在于创建一个无模式的对话框,并在编辑对话框资源时指明 Child风格和无边框风格。然后我们用 ClassWizard创建一个 CDialog的派生类,并进行相关的消息映射。
消息框在 Windows编程里,我们要考虑应用程序运行过程中出现的问题或其它原因要给出简短信息就没有必要创建对话框,
可以直接使用 Windows 系统为我们提供现成的消息对话框。
在 Visual C++中,MFC提供了一个全局函数 AfxMessageBox
和一个封装在 CWnd类中的函数 MessageBox。
int AfxMessageBox( LPCTSTR lpszText,UINT nType =
MB_OK,UINT nIDHelp =0 );
int AFXAPI AfxMessageBox(UINT nIDPrompt,UINT
nType=MB_OK,UINTnIDHelp= (UINT) -1 );