在.NET框架中,RichTextBox控件提供了一种方便的属性DetectUrls,当设置此属性时,控件会自动检测并格式化文本中的URL。但是,这个功能仅限于识别以http:、file:、mailto:等标准协议开头的链接。如果需要添加不以这些协议开头的链接,标准的RichTextBox控件就无法满足需求了。幸运的是,.NET的RichTextBox控件实际上是Win32RichEdit控件的包装,可以通过发送特定的消息来扩展其功能。
RichTextBox控件的DetectUrls属性虽然方便,但它只能识别以特定协议开头的链接。这意味着,如果需要添加自定义的链接样式,比如内部文档链接或者特定应用程序的链接,标准的RichTextBox控件就无能为力了。
RichEdit控件定义了两组消息,一组是EM_GETCHARFORMAT和EM_SETCHARFORMAT,用于设置和查询字符范围内的格式选项;另一组是EM_GETPARAFORMAT和EM_SETPARAFORMAT,用于设置和查询整个段落的格式选项,比如对齐方式。将使用第一组消息来设置所需的样式。
在查阅EM_SETCHARFORMAT的文档时,会发现它使用了一个CHARFORMAT结构来传递格式化信息。对于RichEdit控件的较新版本(2.0及以上),这个结构被扩展为CHARFORMAT2结构,包含了更多的信息。这个结构的定义如下:
typedef struct _charformat2 {
UINT cbSize;
DWORD dwMask;
DWORD dwEffects;
LONG yHeight;
LONG yOffset;
COLORREF crTextColor;
BYTE bCharSet;
BYTE bPitchAndFamily;
TCHAR szFaceName[LF_FACESIZE];
WORD wWeight;
SHORT sSpacing;
COLORREF crBackColor;
LCID lcid;
DWORD dwReserved;
SHORT sStyle;
WORD wKerning;
BYTE bUnderlineType;
BYTE bAnimation;
BYTE bRevAuthor;
BYTE bReserved1;
} CHARFORMAT2;
这个结构中包含了两个成员,dwMask和dwEffects,它们分别用于指定是否要设置/查询某个格式化选项,以及实际的值。其中,CFE_LINK标志正是所需要的,它可以让文本的一部分具有链接的外观和行为。
要告诉RichEdit控件想要为文本的一部分分配特定的字符格式,需要向控件发送Windows消息EM_SETCHARFORMAT。如果对Win32结构的封装和SendMessage()的声明感兴趣,可以查看源代码。
当使用扩展的RichTextBox时,将有几个新的方法可用:
public void InsertLink(string text);
public void InsertLink(string text, int position);
这些方法可以在指定位置(或者如果没有指定,则在当前插入位置)插入链接。如果链接文本由于LinkClicked事件的结果而不适合(例如,如果有多个相同的链接文本,但想引用不同的超链接),还有两个额外的方法,可以指定一个额外的超链接字符串:
public void InsertLink(string text, string hyperlink);
public void InsertLink(string text, string hyperlink, int position);
它们的行为类似于前两个方法,但在链接文本本身之后,会添加一个不可见的超链接字符串,用井号('#')分隔。例如,调用:
InsertLink("在线帮助", "myHelpFile.chm");
将在LinkClickedEventArgs中给出"在线帮助#myHelpFile.chm"。这样,就可以独立管理链接文本和超链接。
有一个细节需要注意。默认情况下,标准RichTextBox的DetectUrls属性是设置的,所以输入的任何内容都会被自动重新格式化。扩展默认情况下将此属性关闭,因为它可能会干扰以编程方式添加的链接。当DetectUrls属性设置为true并且修改了链接旁边的文本时,链接格式将会丢失。当DetectUrls设置为false时,不会发生这种情况,所以建议将其关闭。
就像添加了对CFE_LINK的支持一样,添加对其他格式化标志的支持也应该很容易(例如,CFE_SUBSCRIPT或CFE_SUPERSCRIPT)以添加新的格式化选项。必要的标志定义已经包含在源代码中,所以不必在平台SDK中查找它们了。