VC++60 第十六章 VC++开发工具和MFC基础类库(二)
16.2 MFC类库的基本控件
1 基本控件
基本控件是WINDOWS V3.1就开始使用的控件,也就是本书前面各章逐一介绍的那些控件。它们是最基本的最常用的,主要有按钮、静态正文、编辑框、单选按钮和复选框(英文名Check,有人翻译为检查框)、列表框、组合框、组框(Group)、垂直和水平的滚动条,它们大部分在图chap16-05的工具窗口的前三行。
每个控件都包括ID和标题这两个属性,其它属性则因控件而异,所有属性分三类——Genaral,Styles and Extended Styles。要设计控件属性用右键点击控件即可,你可以打开属性窗口一一考察和试验,我们不可能一一枚举。下面择要介绍编辑框的属性和消息映射。
图chap16-06是编辑框的属性对话框的Styles页。其中,Multiline复选框选中表示创建的是多行编辑框,否则是单行编辑框,那时还可属性对话框的Styles页以选中Password选项。复选框Want return被选中表示能够接受回车键,否则,在编辑框中打回车键后就自动退出应用程序。选中Want return时必须选定一个按钮为默认按钮,打回车键后就自动执行那默认按钮的响应函数。一般地,创建对话框时系统提供的[OK]按钮就是默认按钮,你可以按需要改动。NUmber复选框用来设置“限制输入为数字”。Align组合框用来选定文本对齐方式。属性对话框的其余两页没有什么特殊的地方。
编辑框能够向父窗口发出的控件通知消息键下表,其中EN_CHANGE和EN_UPDATE是两个最重要的。EN_CHANGE消息是是在编辑框显示的正文被刷新后才发出的。而EN_UPDATE消息是在准备显示改变了的正文时发送的。EN_CHANGE的消息映射函数为OnChangeXXXX,EN_UPDATE的消息映射函数为OnUpdateXXXX。
消息 | 含义 |
EN_CHANGE | 编辑框的内容被用户改变了。与EN_UPDATE不同,该消息是在编辑框显示的正文被刷新后才发出的。 |
EN_ERRSPACE | 编辑框控件无法申请足够的动态内存来满足需要。 |
EN_HSCROLL | 用户在水平滚动条上单击鼠标。 |
EN_KILLFOCUS | 编辑框失去输入焦点。 |
EN_MAXTEXT | 输入的字符超过了规定的最大字符数。在没有ES_AUTOHSCROLL 或 ES_AUTOVSCROLL的编辑框中,当正文超出了编辑框的边框时也会发出该消息。 |
EN_SETFOCUS | 编辑框获得输入焦点。 |
EN_UPDATE | 在编辑框准备显示改变了的正文时发送该消息。 |
EN_VSCROLL | 用户在垂直滚动条上单击鼠标。 |
编辑框控件与剪切板有关的成员函数有:
void Copy(), void Cut(), void Paste(), void Clear(), BOOL Undo()。
在编辑框中获得和设置文本要使用CWnd的成员函数
void GetWindowText( CString& rString ) const;
void SetWindowText( LPCTSTR lpszString );
CEdit的成员函数还有:
获得所选正文的位置
DWORD GetSel( ) const;
void GetSel( int& nStartChar, int& nEndChar ) const;
多行编辑框,返回指定字符索引所在行的行索引
int LineFromChar( int nIndex = –1 ) const;
用于多行编辑框,获得指定行的开头字符的字符索引
int LineIndex( int nLine = –1 ) const;
用于多行编辑框,获得正文的行数
int GetLineCount( ) const;
获取指定字符索引所在行的长度
int LineLength( int nLine = –1 ) const;
用于多行编辑框,用来获得指定行的正文
int GetLine( int nIndex, LPTSTR lpszBuffer ) const;
int GetLine( int nIndex, LPTSTR lpszBuffer, int nMaxLength ) const;
选择编辑框中的正文,参数dwSelection的低位字说明了选择开始处的字符索引,高位字说明了选择结束处的字符索引。
void SetSel( DWORD dwSelection, BOOL bNoScroll = FALSE );
void SetSel( int nStartChar, int nEndChar, BOOL bNoScroll = FALSE );
用来将所选正文替换成指定的正文
void ReplaceSel( LPCTSTR lpszNewText, BOOL bCanUndo = FALSE );
可以利用LineIndex和LineFromChar来在字符索引和字符的行列坐标之间相互转换.下列代码演示了在已知字符索引的情况下,如何获得对应的行列坐标:
int row,column;
row=MyEdit.LineFromChar(charIndex);
column=charIndex-MyEdit.LineIndex(row);
下列代码演示了在已知字符的行列坐标的情况下,如何获得对应的字符索引:
int charIndex;
charIndex=MyEdit.LineIndex(row)+column;
不难看出字符索引与对应的行列坐标的关系是:
列坐标=字符索引-LineIndex(行坐标)
2 Win32新控件
从Windows 95开始,Windows提供了一些先进的Win32控件.这些新控件弥补了传统控件的某些不足之处,并使Windows的界面丰富多彩且更加友好。大概是当时计算机的字长已经从16位扩展到了32位的缘故吧,所以它们称为Win32控件。
较之传统的Windows 3.x控件,新的Win32控件更加复杂和先进.在新控件发送通知消息的同时,往往还需要附加一些数据来描述控件的状态.传统的WM_COMMAND消息通知机制显然不能完成这一任务,因为WM_COMMAND消息的wParam和lParam已经被占满了,无法容纳新的数据。在Win32中,采用新的WM_NOTIFY消息来实现新控件的消息通知机制.在该消息的wParam中含有控件的ID,lParam中则有一个指针,这个指针指向一个结构.这个结构是NMHDR结构,或者是一个以NMHDR结构作为第一个成员的扩充结构。下表给出了新的Win32控件及其功能和控件类。
控件名 | 功能 | 对应的控件类 |
动画(Animate) | 可播放avi文件. | CAnimateCtrl |
热键(Hot Key) | 使用户能选择热键组合. | CHotKeyCtrl |
列表视图(List View) | 能够以列表、小图标、大图标或报告格式显示数据. | CListCtrl |
进度条(Progress Bar) | 用于指示进度. | CProgressCtrl |
滑尺(Slider) | 也叫轨道条(Trackbar),用户可以移动滑尺来在某一范围中进行选择. | CSliderCtrl |
旋转按钮(Spin Button) | 有时被称为上下控件.有一对箭头按钮,用来调节某一值的大小. | CSpinButtonCtrl |
标签(Tab) | 用来作为标签使用. | CTabCtrl |
树形视图(Tree View) | 以树状结构显示数据. | CTreeCtrl |
传统控件和Win32 控件采用了不同的通知消息机制,下表给出了新的Win32控件共有的通知消息。
通知消息码 | 含义 |
NM_CLICK | 用户在控件上单击鼠标左键. |
NM_DBLCLK | 用户在控件上双击鼠标左键. |
NM_RCLICK | 用户在控件上单击鼠标右键. |
NM_RDBLCLK | 用户在控件上双击鼠标右键. |
NM_RETURN | 用户在控件上按回车键. |
NM_SETFOCUS | 控件获得输入焦点. |
NM_KILLFOCUS | 控件失去输入焦点. |
NM_OUTOFMEMORY | 内存不够. |
这些新的Win32控件的设计和使用的方法和技巧是本书下一册要研究的对象。
3 菜单和公用对话框
1) 菜单
在第四章中我们详细介绍了在对话框中添加菜单的设计过程。而文档模式下菜单是可以由系统自动生成的,而修改菜单的方法是一样的,其属性窗口中主要有如下内容:
属性“选中的”使菜单项在开始时置为选中状态,这主要用于该菜单设置为带BOOL值的情况。属性“非激活”使该菜单项是不活动的,即鼠标点上去是无效的。“变灰”属性则使该菜单的外观变灰色,即无效色,同时属性“非激活”自动被设定。如果您选中“弹出”选项,那它就成了一个弹出式子菜单,如图08所示。
如果菜单标题有中文去不能正确显示,那一定是菜单的语言属性设置为英文了。在工作区的资源页中右击该菜单,在快捷菜单中选“属性\语言”, 把它设置为简体中文就行了。
如果要给窗口添加一个快捷菜单,那就需要打开VC++的菜单项“工程/添加到工程”;从中选择Compoents and Contorls;在对话框中选择Visual C++ Components;在组件对话框中选择POP_UP MENU组件,点击[Ineart]按钮;此时弹出的对话框要您选择快捷菜单是添加到哪个窗口上的;最后点[结束]按钮就OK了。快捷菜单项的属性和命令函数等的设计和普通菜单一样。
2) 公用对话框
公用对话框是指文件对话框、字体、颜色、查找和替换以及打印对话框,他们是VC++封装好了的MFC的公用对话框。公用对话框的创建过程与一般对话框类似,首先是在堆栈上构建一个CFileDialog对象,然后调用DoModal()来启动对话框。
(1) 文件对话框
文件对话框CFileDialog类用于文件的打开和保存操作。首先是在堆栈上构建一个CFileDialog对象,然后调用CFileDialog::DoModal函数来启动对话框。文件对话框的构造函数为
CFileDialog( BOOL bOpenFileDialog,
LPCTSTR lpszDefExt = NULL,
LPCTSTR lpszFileName = NULL,
DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
LPCTSTR lpszFilter = NULL, CWnd* pParentWnd = NULL );
如果参数bOpenFileDialog的值为TRUE,将创建Open(打开文件)对话框,否则就创建Save As(保存文件)对话框。参数lpszDefExt用来指定缺省的文件扩展名。lpszFileName用于规定初始文件名。dwFlags用于设置对话框的一些属性。lpszFilter指向一个过滤字符串,用户如果只想选择某种或某几种类型的文件,就需要指定过滤字符串。参数pParentWnd是指向父窗口或拥有者窗口的指针。
过滤字符串有特定的格式,它实际上是由多个子串组成,每个子串由两部分组成,第一部分是过滤器的字面说明,如“Text file (*.txt)”,第二部分是用于过滤的匹配字符串,如“*.txt”,子串的两部分用竖线字符“ | ”分隔开。各子串之间也要用“ | ”分隔,且整个串的最后两个字符必须是两个连续的竖线字符“ || ”。一个典型的过滤字符串如下面所示:
char szFilter[]=“All files (*.*)|*.*|Text files(*.txt)|*.txt|Word documents(*.doc)|*.doc||”;
若CFileDialog::DoModal返回的是IDOK,那么可以用下表列出的CFileDialog类的成员函数来获取相关的文件信息。
函数名 | 用途 |
GetPathName | 返回一个包含有全路径文件名的CString对象。 |
GetFileName | 返回一个包含有文件名(不含路径)的CString对象。 |
GetFileExt | 返回一个只含文件扩展名的CString对象。 |
GetFileTitle | 返回一个只含文件名(不含扩展名)的CString对象。 |
(2)字体对话框
字体对话框CFontDialog类的构造函数如下所示
CFontDialog( LPLOGFONT lplfInitial = NULL,
DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,
CDC* pdcPrinter = NULL,
CWnd* pParentWnd = NULL );
参数lplfInitial指向一个LOGFONG结构,用来初始化对话框中的字体设置。dwFlags用于设置对话框。pdcPrinter指向一个代表打印机的CDC对象,若设置该参数,则选择的字体就为打印机所用。pParentWnd用于指定对话框的父窗口或拥有者窗口。若DoModal返回IDOK,那么可以调用CFontDialog的下列成员函数来获得所选字体的信息。
函数名 | 用途 |
GetCurrentFont | 用来获得所选字体的属性。该函数有一个参数,该参数是指向LOGFONT结构的指针,函数将所选字体的各种属性写入这个LOGFONT结构中。 |
GetFaceName | 返回一个包含所选字体名字的CString对象。 |
GetStyleName | 返回一个包含所选字体风格名字的CString对象。 |
GetSize | 返回所选字体的尺寸(以10个象素为单位)。 |
GetColor | 返回一个含有所选字体的颜色的COLORREF型值。 |
GetWeight | 返回所选字体的权值。 |
IsStrikeOut | 若用户选择了空心效果则返回TRUE,否则返回FALSE。 |
IsUnderline | 若用户选择了下划线效果则返回TRUE,否则返回FALSE。 |
IsBold | 若用户选择了黑体风格则返回TRUE,否则返回FALSE。 |
IsItalic | 若用户选择了斜体风格则返回TRUE,否则返回FALSE。 |
(3)颜色对话框
颜色对话框CColorDialog的构造函数为
CColorDialog( COLORREF clrInit = 0,
参数clrInit用来指定初始的颜色选择,dwFlags用来设置对话框,pParentWnd用于指定对话框的父窗口或拥有者窗口。根据DoModal返回的是IDOK还是IDCANCEL可知道用户是否确认了对颜色的选择。DoModal返回后,调用CColorDialog::GetColor()可以返回一个COLORREF类型的结果来指示在对话框中选择的颜色。COLORREF是一个32位的值,用来说明一个RGB颜色。GetColor返回的COLORREF的格式是0x00bbggrr,即低位三个字节分别包含了蓝、绿、红三种颜色的强度。
(4)打印对话框
打印对话框CPrintDialog类的构造函数:
CPrintDialog( BOOL bPrintSetupOnly,
参数bPrintSetupOnly的值若为TRUE,则创建的是Print对话框,否则,创建的是Print Setup对话框。dwFlags用来设置对话框,缺省设置是打印出全部页,禁止From和To编辑框(即不用确定要打印的页的范围),PD_USEDEVMODECOPIES使对话框判断打印设备是否支持多份拷贝和校对打印(Collate),若不支持,就禁止相应的编辑控件和Collate检查框。pParentWnd用来指定对话框的父窗口或拥有者窗口。程序可以调用CPrintDialog的成员函数来获得打印参数。
函数名 | 用途 |
GetCopies | 返回要求的拷贝数。 |
GetDefaults | 在不打开对话框的情况下返回缺省打印机的缺省设置,返回的设置放在m_pd数据成员中。 |
GetDeviceName | 返回一个包含有打印机设备名的CString对象。 |
GetDevMode | 返回一个指向DEVMODE结构的指针,用来查询打印机的设备初始化信息和设备环境信息。 |
GetDriverName | 返回一个包含有打印机驱动程序名的CString对象。 |
GetFromPage | 返回打印范围的起始页码。 |
GetToPage | 返回打印范围的结束页码。 |
GetPortName | 返回一个包含有打印机端口名的CString对象。 |
GetPrinterDC | 返回所选打印设备的一个 HDC 句柄。 |
PrintAll | 若要打印文档的所有页则返回TRUE。 |
PrintCollate | 若用户选择了Collate Copies检查框(需要校对打印拷贝)则返回TRUE。 |
PrintRange | 如果用户要打印文档的一部分页,则返回TRUE。 |
PrintSelection | 若用户想打印当前选择的部分文档,则返回TRUE。 |
(5)查找和替换对话框
查找替换对话框CFindReplaceDialog类用于实现Find(搜索)和Replace(替换)对话框,由于Find和Replace对话框这两个对话框都是非模式对话框,它们的创建方式与其它四类公用对话框不同。CFindReplaceDialog对象是用new操作符在堆中创建的,而不是象普通对话框那样以变量的形式创建。要启动Find/Replace对话框,应该调用CFindReplaceDialog::Create函数,而不是DoModal。Create函数的声明是
BOOL Create( BOOL bFindDialogOnly,
当参数bFindDialogOnly的值为TRUE时,创建的是Find对话框,为FALSE时创建的是Replace对话框。参数lpszFindWhat指定了要搜索的字符串,lpszReplaceWith指定了用于替换的字符串。dwFlags用来设置对话框,其缺省值是FR_DOWN(向下搜索),该参数可以是几个FR_XXX常量的组合,用户可以通过该参数来决定诸如是否要显示Match case、Match Whole Word检查框等设置。参数pParentWnd指明了对话框的父窗口或拥有者窗口。
Find/Replace对话框与其它公用对话框的另一个不同之处在于它在工作过程中可以重复同一操作而对话框不被关闭,这就方便了频繁的搜索和替换。CFindReplaceDialog类只提供了一个界面,它并不会自动实现搜索和替换功能。CFindReplaceDialog使用了一种特殊的通知机制,当用户按下了操作的按钮后,它会向父窗口发送一个通知消息,父窗口应在该消息的消息处理函数中实现搜索和替换。
CFindReplaceDialog类提供了一组成员函数用来获得与用户操作有关的信息,如下表8所示,这组函数一般应在通知消息处理函数中调用。
函数名 | 用途 |
FindNext | 如果用户点击了Findnext按钮,该函数返回TRUE。 |
GetNotifier | 返回一个指向当前CFindReplaceDialog对话框的指针。 |
GetFindString | 返回一个包含要搜索字符串的CString对象。 |
GetReplaceString | 返回一个包含替换字符串的CString对象。 |
IsTerminating | 如果对话框终止了,则返回TRUE。 |
MatchCase | 如果选择了对话框中的Match case检查框,则返回TRUE。 |
| 如果选择了对话框中的Match Whole Word检查框,则返回TRUE。 |
ReplaceAll | 如果用户点击了Replace All按钮,该函数返回TRUE。 |
ReplaceCurrent | 如果用户点击了Replace按钮,该函数返回TRUE。 |
SearchDown | 返回TRUE表明搜索方向向下,返回FALSE则向上。 |
CEditView类自动实现了Find和Replace对话框的功能,但MFC AppWizard并未提供相应的菜单命令。读者可以在前面的Register工程的Edit菜单中加入&Find...和&Replace...两项,并令其ID分别为ID_EDIT_FIND和ID_EDIT_REPLACE,则Find/Replace对话框的功能就可以实现。