摘要: 本文对Rich Edit控件底层消息机制进行了讲解,以期读者对Windows平台下的Rich Edit控件有一个更深入的认识,同时对于使用Win32 SDK进行开发的人员具有一定参考价值。因为文章的初衷是引领VB程序员通过Win32 API调用来扩展VB下的Rich Edit控件的功能,所以对于每个消息的详细说明和注意事项未作过多说明,感兴趣的朋友可以参考Visual Studio下的MSDN Library。
关键字:Rich Edit Control、RTF、SDK、MSDN。
Rich Edit控件是一个可用于输入、编辑、格式化、打印和保存文本的窗体。这些文本可以设置字符和段落格式,并且可以包含嵌入的COM对象。Rich Edit控件提供格式化文本的编程接口。不过,应用程序必须实现这些用户接口组件,以便用户可以进行格式化操作。
Rich Edit控件几乎支持所有用于多行Edit控件的消息和通知。因此,已经使用了Edit控件的程序可以很容易的改为Rich Edit控件。额外的消息和通知使得应用程序可以访问Rich Edit控件特有的功能。获取更多关于Edit控件的信息,请参阅Edit Controls。
正如大家所熟知的,Windows控件是基础窗口,它处理那些控制窗口显示和特征的消息。而ActiveX控件是把那些消息变成属性和方法的COM 容器。RichEdit Windows控件是Edit Windows控件的扩展集,TextBox ActiveX控件也是从它派生而来。RichEdit能够识别Edit消息并且加入了自己特有的消息。你可以在Win32帮助文件中认出Edit和RichEdit的消息常数,因为他们均采用EM_作为前缀。
ActiveX RichTextBox控件将绝大多数的这种消息映射为其属性。例如,EM_LIMITTEXT与MaxLength属性相对应。但是你同时会注意到一些感兴趣的消息并没有与之对应的RichTextBox属性。为什么呢?
ActiveX控件为最通用的特性提供方法和属性,更具体讲,是提供给VB设计者最感兴趣的特性。设计者们似乎喜欢每个新版本里更多的特征。 例如,TextBox 和RichTextBox控件现在具备Locked属性。在旧版本的VB中你不得不通过EM_SETREADONLY消息来模拟。但是,还有许多其他隐藏的或者不是很明显的特性在ActiveX控件中尚未提供。为了使用这些特性,我们就必须对Rich Edit控件的底层消息机制进行较深入的了解。
Rich Edit控件的最初规范为1.0版。目前规范为2.0版。(译者注:目前最新版本为4.1版本!)在创建一个Rich Edit控件之前,你应该调用LoadLibrary函数来确认安装的Rich Edit控件的版本。下表显示了不同版本与其DLL间的对应关系。
Rich Edit 版本 |
DLL名称 |
版本号 |
1.0 |
RICHED32.DLL |
|
2.0 |
RICHED20.DLL |
低于<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" /><chsdate w:st="on" year="1899" month="12" day="30" islunardate="False" isrocdate="False"><span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Arial','sans-serif'">5.30.23</span></chsdate>.1200 |
3.0 |
RICHED20.DLL |
<chsdate w:st="on" year="1899" month="12" day="30" islunardate="False" isrocdate="False"><span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Arial','sans-serif'">5.30.23</span></chsdate>.1200或更高 |
4.1 |
Msftedit.dll |
|
下表给出了不同版本Windows下与其包含的不同版本的Rich Edit对应关系:
Windows XP SP1 |
包含 Rich Edit 4.1, Rich Edit 3.0, 和一个 Rich Edit 1.0 仿真程序。 |
Windows XP |
包含Rich Edit 3.0和一个 Rich Edit 1.0 仿真程序。 |
Windows Me |
包含Rich Edit 1.0和3.0。 |
Windows 2000 |
包含Rich Edit 3.0和一个 Rich Edit 1.0 仿真程序。 |
Windows NT 4.0 |
包含Rich Edit 1.0和2.0。 |
Windows 98 |
包含Rich Edit 1.0和2.0。 |
Windows 95 |
只包含Rich Edit 1.0。不过,Riched20.DLL与Windows 95系统兼容,所以可以在正确安装后使用。 |
Rich Edit 2.0包含几个新特性,比如支持Unicode和远东语言,多级撤消,以及大量的增强用户接口。
Rich Edit 2.0采用与Rich Edit 1.0一致的Win32函数,结构和消息,极少例外。他们的区别在于:
消息 |
描述 |
EM_AUTOURLDETECT |
是否开启/关闭自动URL检测。 |
EM_CANREDO |
判断是否在Redo队列中有一些动作。 |
EM_GETIMECOMPMODE |
获取当前输入方式编辑(IME)模式。 |
EM_GETLANGOPTIONS |
获取IME和远东语言支持选项。 |
EM_GETREDONAME |
获取Redo队列中的下一动作的类型名称。 |
EM_GETTEXTMODE |
获取文本模式或者Undo级别。 |
EM_GETUNDONAME |
获取Undo队列中的下一动作的类型名称。 |
EM_REDO |
重做Redo队列中的下一动作。 |
EM_SETLANGOPTIONS |
设置IME和远东语言支持选项。 |
EM_SETTEXTMODE |
设置文本模式或者Undo级别。 |
EM_SETUNDOLIMIT |
设置Undo队列的最大动作数目。 |
EM_STOPGROUPTYPING |
终止当前Undo动作的连续键入动作的组合。 |
消息 |
描述 |
CHARFORMAT2 |
包含字符格式信息。 |
PARAFORMAT2 |
包含段落格式属性。 |
EM_CONVPOSITION |
EM_GETIMECOLOR |
EM_GETIMEOPTIONS |
EM_GETPUNCTUATION |
EM_GETWORDWRAPMODE |
EM_SETIMECOLOR |
EM_SETIMEOPTIONS |
EM_SETPUNCTUATION |
EM_SETWORDWRAPMODE |
可用通过CreateWindowEx函数中指定Rich Edit 窗体类来创建一个Rich Edit控件。如果使用1.0版本(RICHED32.DLL),窗体类参数应该为“RichEdit”。如果采用2.0版本(RICHED20.DLL),窗体类参数应该为“RICHEDIT_CLASS”。
Rich Edit控件支持大部分的Edit控件采用的窗体样式,同时也支持一些额外的样式。你如果希望控件中的文本支持不止一行的话就应该给出ES_MULTILINE窗体样式。
应用程序可以通过给Rich Edit控件发送消息来格式化字符和段落以及获取这些格式化信息。段落格式属性包含对齐、跳格、缩进和编号。对字符而言,你可以指定字体、尺寸、颜色以及如粗体、斜体和保护等效果。
你可以采用EM_SETPARAFORMAT消息来应用段落格式。获取当前选中文本的段落格式属性,则采用EM_GETPARAFORMAT消息。PARAFORMAT结构将会在这两个消息中用到,它用于描述段落格式属性。
你可以采用EM_SETCHARFORMAT消息来应用字符格式。获取当前选中文本的字符格式属性,则采用EM_GETCHARFORMAT消息。CHARFORMAT结构将会在这两个消息中用到,它用于描述字符格式属性。
你也可以采用EM_SETCHARFORMAT和EM_GETCHARFORMAT消息来设置和获取默认字体格式,它将应用于所有随后插入的字符。例如,应用程序将默认字符格式设置为粗体,则用户随后敲入的字符都将为粗体。
只有在当前选择内容为空的时候默认字符格式才会被应用到新插入的文本上。否则,新的文本将假定沿用其所替换的文本的格式。如果选择内容改变,则默认字体格式将将采用该内容的首字符的格式。
保护(Protected)字符效果是唯一不改变其文本显示的例子。如果用户试图修改保护文本,Rich Edit控件将发送EN_PROTECTED通知到其父窗口,让其父窗体决定是否允许或者拒绝修改。为了接收该通知,你必须使用EM_SETEVENTMASK消息来启用它。
前景色是一个字符属性,但是背景色是一个Rich Text控件属性。要设置背景色,请采用EM_SETBKGNDCOLOR消息。
用户可以在Rich Edit控件中通过鼠标和键盘来选择文本。当前选择内容指的是选中字符的范围,或者表示没有字符选中时的插入点位置。应用程序可以获取选中内容的相关信息,设置当前选中内容,决定当前选中内容何时改变,显示或者隐藏当前高亮显示的选中内容等。
确定Rich Edit控件中的当前选中内容,采用EM_EXGETSEL消息。设置当前选择区域,采用EM_EXSETSEL消息。CHARRANGE结构用于在这两个消息中描述字符范围。获取当前选中内容的相关信息,你可以采用EM_SELECTIONTYPE消息。
应用程序可以通过处理EN_SELCHANGE通知来检测当前选中内容何时被改变。该通知通过SELCHANGE结构给出新选中内容的相关信息。Rich Edit控件只有在你通过EM_SETEVENTMASK消息开启它之后才会发送该通知。
默认情况下,Rich Edit控件在获取和失去焦点时将开启和隐藏选中文本的高亮显示。你可以通过EM_HIDESELECTION消息在任何时候开启或者隐藏选中区域的高亮显示。例如,某个应用程序可能提供一个查找对话框用于在Rich Edit控件中查找文本,这种情况下就必须使用EM_HIDESELECTION消息来保持选中文本的高亮显示。
与Edit控件一样,你可以使用ES_NOHIDESEL窗体样式来防止Rich Edit控件在失去焦点时隐藏选中区域的高亮显示。你也可以在Rich Edit控件创建之后使用EM_HIDESELECTION消息来改变窗体的ES_NOHIDESEL样式。
获取和设置当前选中内容使用EM_GETSEL和EM_SETSEL Edit控件消息,而非EM_EXGETSEL和EM_EXSETSEL消息。EM_GETSEL消息将两个16位字符索引压缩为它的32位返回值,因此,仅仅适用于选中区域的前64K字节。然而,一个Rich Edit控件不可能包含超过32K字节的文本,除非你使用EM_EXLIMITTEXT消息扩展了这个限制。对于选中文本中超过前64K字节的文本,EM_GETSEL消息将返回-1。
应用程序可以发送消息来获取或者查找Rich Edit控件中的文本。你既可以获取选中区域的文本也可以获取给定范围的文本。
获取Rich Edit控件中的选中文本,使用EM_GETSELTEXT消息。文本将被拷贝到指定字符数组中。你必须确保数组大小足以容纳选中文本再加上一个终止NULL字符。
获取给定范围的文本,使用EM_GETTEXTRANGE消息。该消息将使用TEXTRANGE结构,用于描述需要获得的文本范围以及用于获取该文本的字符数组指针。在这里,同样的,你必须确保数组大小足以容纳选中文本再加上一个终止NULL字符。
你可以使用EM_FINDTEXT消息在一个Rich Edit控件中查找字符串。该消息将使用结构,用于描述文本查找范围及需要查找的字符串。你也可以指定诸如是否区分大小写等搜索选项。
Rich Edit 控件调用叫做“断字处理过程”的函数来查找单词间分隔符以及判断何处可以换行。控件在执行自动换行操作时以及处理Ctrl+左箭头和Ctrl+右箭头的组合键时将利用这些信息。应用程序可以通过向Rich Edit控件发送消息来替换默认的“断字处理过程”,获取断字信息,以及判断一个给定字符属于哪一行。
Rich Edit控件的断字处理过程与Edit控件相似,但是它拥有更多能力。两种控件的断字处理过程均可以识别一个字符是否是一个分隔符,并且能够在找到给定位置的前一个或者后一个字分隔符。分隔符指的是一个标志单词结束的字符,比如空格。在Edit控件中,断字只出现在分隔符之后。
Rich Edit控件的断字处理过程同时将字符组合为字符类,由到0x00的0x<chmetcnv w:st="on" unitname="F" sourcevalue="0" hasspace="False" negative="False" numbertype="1" tcsc="0">0F</chmetcnv>值来标识。断字可以出现在分隔符之后或者在不同类的字符之间。因此,在字符串“WIN.COM”中,由于字母数字和标点属于不同类别,断字程序将找到两个字分隔符。
一个字符类别可以由0个或