使用Windows标准控件我们在前面曾提到过,控件是一些行为标准化了的窗口,一般用于对话框或其它窗口中充当与用户交互的元素。在VisualC++中,可以使用的控件分成三类:(1)Windows标准控件Windows标准控件由Windows操作系统提供,在Windows95中还提供了一些新增的控件。所有这些控件对象都是可编程的,我们可以使用VisualC++提供的对话框编辑器把它们添加到对话框中。Microsoft基础类库(MFC)提供了封装这些控件的类,它们列于表6.1。表6.1Windows标准控件控件MFC类描述动画CAnimateCtrl显示连续的AVI视频剪辑按钮CButton用来产生某种行为的按钮,以及复选框、单选钮和组框组合框CComboBox编辑框和列表框的组合编辑框CEdit用于键入文本标题头CHeaderCtrl位于某一行文本之上的按钮,可用来控制显示文件的宽度热键CHotKeyCtrl用于通过按下某一组合键来很快的执行某些常用的操作图象列表CImageList一系列图象(典型情况下是一系列图标或位图)的集合。图象列表本身不是一种控件,它常常是和其它控件一起工作,为其它控件提供所用的图象列表列表CListCtrl显示文本及其图标列表的窗口列表框CListBox包括一系列字符串的列表进度CProgressCtrl用于在一较长操作中提示用户所完成的进度多格式文本编辑CRichEditCtrl提供可设置字符和段落格式的文本编辑的窗口滚动条CScrollBar为对话框提供控件形式的滚动条滑块CSliderCtrl包括一个有可选标记的滑块的窗口旋转按钮CSpinButtonCtrl提供一对可用于增减某个值的箭头静态文本CStatic常用于为其它控件提供标签状态条CStatusBarCtrl用于显示状态信息的窗口,同MFC类CStatusBar类似续表6.1控件MFC类描述选项卡CTabCtrl在选项卡对话框或属性页中提供具有类似笔记本中使用的分隔标签的外观的选项卡工具条CToolBarCtrl具有一系列命令生成按钮的窗口,同MFC类CToolBar类似工具提示CToolTipCtrl一个小的弹出式窗口,用于提供对工具条按钮或其它控件功能的简单描述树CTreeCtrl用于显示一系列的项的继承结构前面提到过,在MFC中,类CWnd是所有窗口类的基类,很自然的,它也是所有控件类的基类。Windows标准控件在以下环境下提供:•Windows95•WindowsNT3.51及以后版本•Win32s1.3•注意:•VisualC++4.2及以后版本不再支持Win32s。(2)ActiveX控件ActiveX控件可用于对话框中,也可用于HTML文档中。这种控件过去被称为OLE控件。本书将在专门的章节中来讲述关于ActiveX控件的知识。这里仅指出ActiveX控件使用了与标准控件完全不同的接口和实现方法。(3)其它MFC控件类除了Windows标准控件和自己编写的或者来自于第三方软件开发商的ActiveX控件以外,MFC还提供了另外三种控件,它们由下面的三个类进行封装:•类CBitmapButton用于创建以位图作为标签的按钮,位图按钮昀多可以包括四个位图图片,分别代表按钮的四种不同状态。•类CCheckListBox用于创建选择列表框,这种列表框中的每一项前面有一个复选框,以决定该项是否被选中。•类CDragListBox用于创建一种特殊的列表框,这种列表框允许用户移动列表项。在本章我们仅讲述第一类控件,即Windows标准控件。所涉及的内容包括各个控件的使用及相应的技巧。第一节使用对话框编辑器和ClassWizard对于大多数Windows标准控件,我们一般都使用对话框编辑器来将它们添加到对话框中。图6.1在ResourceView中选择对话框IDD_DIALOGDEMO_DIALOG图6.2控件的Properties对话框图6.3对话框编辑器的Controls工具窗口在下面的过程中,我们将一个编辑框控件添加到在第四章创建的基于对话框的MFC框架应用程序的主对话框窗口中。1.首先,在Workspace窗口的ResourceView选项内双击DialogDemoresources\Dialog节点下的IDD_DIALOGDEMO_DIALOG图标。上面的操作如图所示。2.用鼠标选中标有“要做……”的静态文本控件。右击鼠标,从上下文菜单中选择Properties,打开如图6.2所示的对话框,在Caption文本框中输入新的控件文本:“在下面的文本框中输入一些字符”,然后将静态文本控件拖动到对话框的左上角。3.从Controls工具窗口(如图6.3所示,如果在你的资源编辑器中看不到该工具窗口,可以在工具条上右击鼠标,从上下文菜单中选择Controls)中选择编辑控件图标,在对话框中绘制一个编辑框控件,如图6.4所示。在该编辑框控件的Properties窗口的General选项卡中输入其ID为IDC_EDIT。然后在Styles选项卡下将Multiline复选框划上勾,并消除AutoHScroll复选框前的勾。4.右击该编辑框控件,从上下文菜单中选择ClassWizard命令,打开ClassWizard对话框,该对话框看起来如图6.5所示。图6.4向对话框中添加一个编辑框控件图6.5ClassWizard对话框单击MemberVariables选项卡,确信在Project处选择了DialogDemo,在Classname处选择了CDialogDemoDlg。现在我们为刚才添加的编辑框控件IDC_EDIT添加一个数据映射入口。在ControlIDs处选择IDC_EDIT,单击右边的AddViable按钮。打开如图6.6所示的对话框。在Membervariablename处链接变量名m_strEdit(这里m表示该变量为类CDialogDemoDlg的一个成员变量,str表明其类型为字符串,即类CString),在Category下拉列表中选择Value(另一种选择是Control,两种选择的不同将在后面的内容中讲述),在Variabletype下拉列表中选择CString(还有其它很多数据类型可供选择,但由于这里编辑框中的内容为一字符串,因此CString是昀恰当的选择)。单击OK关闭对话框。图6.6为控件映射添加成员变量5.检查一下现在的ClassWizard对话框(图6.7)与图6.5相比有何不同。在图6.7所示的对话框中下方的Maximumcharacters文本框中输入50。由字面意思可以很容易猜出其含义,即将编辑框IDC_EDIT中可能的昀长字符串的大小限制为50。单击OK关闭对话框。图6.7使用ClassWizard设置数据验证方案6.从Workspace窗口的ClassView中双击类CDialogDemoDlg的OnInitDialog成员函数,使用下面的代码来代替位于语句returnTRUE;前的//TODO注释:m_strEdit=您好!请在这里输入一些字符串。;UpdateData(FALSE);7.在ClassView中双击类CDialogDemoApp的InitInstance成员函数,使用下面的代码来找替位于选择支if(nResponse==IDOK)下的//TODO注释:AfxMessageBox(dlg.m_strEdit);然后将同一成员函数中的下面的代码行删掉(或注释掉):m_pMainWnd=&dlg;8.编译并运行该应用程序。显示如图6.8所示的对话框。图6.8示例程序DialogDemo的运行结果在图6.8所示的文本框中输入一些字符,单击“确定”。随即弹出如图6.9所示的消息框。该消息框复述了用户在图6.8所示的对话框中的输入。我们还发现,在图6.8所示的对话框中,当输入字符串达到一定的长度之后,我们不可以再输入更多的字符,这是我们在前面设置了Maximumcharacters为50的结果。图6.9以消息框的形式反馈输入的字符串下面我们来看在上面的步骤中都完成了什么。首先我们使用资源编辑器向对话框模板中添加这些标准控件,这一步的概念很清晰,因此并不难理解。然后,我们打开了所绘制的编辑框的Properties(属性)对话框。先将其控件ID设置为IDC_EDIT。这时如果打开头文件Resource.h,就会发现宏IDC_EDIT被定义为常量1001。不过,事实上在很多情况下我们并不需要关心每一控件的ID的具体值,而只需要记住相应的助记符。对于这里的编辑框控件,我们只需要记住IDC_EDIT即可,而不需要关心它等于1001。接着,我们在Styles选项卡中设置了Multiline属性,同时清除了AutoHScroll属性,两者共同作用使用得编辑框IDC_EDIT支持多行文本,并且如文本行的长度超过编辑框宽度时自动回行。下面的步骤是昀重要的一步,我们动用了功能强大的工具ClassWizard。首先,我们将编辑框与一个CString对象相关联,这使用了一种被称为DialogDataExchange(DDX)的机制。在这种机制中,我们先在处理函数OnInitDialog或对话框类的构造函数中对对话框对象的成员变量进行初始化,在对话框显示之前,框架的DDX机制将成员变量的值传递给对话框中的控件。这个过程在成员函数DoModal或Create被调用的过程中发生。类CDialog中对OnInitDialog成员函数的默认实现调用了类CWnd成员函数UpdateData来初始化对话框中的控件。这时我们就可以看到前面的第6步还可在具有下面的几种变通方案:1.将代码行m_strEdit=您好!请在这里输入一些字符串。;移到对基类的OnInitDialog成员函数的调用之前,即位于下面的代码之前:CDialog::OnInitDialog();2.将代码m_strEdit=您好!请在这里输入一些字符串。;移到类CDialogDemoDlg的构造函数中。对于上面的两种方法,与前面第6步中使用的方法相比,我们没有必要调用类CWnd的成员函数UpdateData。因为该函数在类CDialog的成员函数OnInitDialog中将被调用。这三种方法之间并没有明确的优劣之分,在很多情况下,它们分别适用于不同的场合。这里我们说一下成员函数UpdateData。该函数带有一个布尔类型的参数,如果该参数为FALSE,函数UpdateData将成员变量的值传递给对话框的变量;而如果该参数为TRUE,函数UpdateData将进行相反的过程。如果用户单击了对话框中ID为IDOK的按钮,或者以TRUE为参数调用函数UpdateData,DDX机制从控件中将值传递到成员变量,同时对话框数据验证(dialogdatavalidation,DDV)机制根据设定的验证规则验证所有数据项。在数据交换的过程中,成员函数UpdateData先创建一个CDataExchange对象,然后调用对话框对类CDialog成员函数DoDataExchange的重载版本。该CDataExchange对象将作为成员函数DoDataExchange的一个参数,该参数定义了数据交换的上下文。在DoDataExchange中,我们为每一个数据成员指定了一个对DDX函数的调用。每一个函数定义了基于由成员函数UpdateData所提供的CDataExchange参数所确定的上下文而进行的双向数据交换。下面的代码摘自实现文件DialogDemo.cpp中对函数DoDataExchange的定义:voidCDialogDemoDlg::DoDataExchange(CDataExchange*pDX){CDialog::DoDataExchange(pDX);//{{AFX_DATA_MAP(CDialogDemoDlg)DDX_Text(pDX,IDC_EDIT,m_strEdit);DDV_MaxChars(pDX,m_strEdit,50);//}}AFX_D