RichEdit 控件:语法高亮显示

时间:2005-12-20 来源: 作者: 点击:
Theory 语法高亮显示对那些编写文本编辑器的人来说是一个热点主题。最好的解决方法(我自己认为的)是编写一个定制的Edit控件,这也是很多商业软件所使用的方法。然而,对于那些没什么时间来编写这么一个控件的人来说,次策就是改写现有的控件使之符合我们的需要。 让我
  Theory

语法高亮显示对那些编写文本编辑器的人来说是一个热点主题。最好的解决方法(我自己认为的)是编写一个定制的Edit控件,这也是很多商业软件所使用的方法。然而,对于那些没什么时间来编写这么一个控件的人来说,次策就是改写现有的控件使之符合我们的需要。

让我们看一看,到底 RichEdit 控件提供了什么功能来帮助我们实现语法高亮。现在我应该声明,下面的方法不是一个“正确”方法:我只是给你们指出那些缺陷。 RichEdit 控件提供了EM_SETCHARFORMAT 消息,是你可以用来改变正文颜色。乍一看,这个消息好象是一个完美的解决方法(我之所以知道是因为我也是其中的一个受骗者)。然而靠近看看,将会发现有几个不合意的地方:

  • EM_SETCHARFORMAT 仅仅对选定的正文或者控件中所有的正文有影响。如果你想改变正文颜色(高亮显示某一个特定的词),你必须先选定它。
  • EM_SETCHARFORMAT 执行速度很慢。
  • RichEdit 控件中的插入点位置处理也有一点问题。

通过上面的讨论,你可以看到使用 EM_SETCHARFORMAT 是一个错误的选择,我会给你演示 "相当正确" 的选择。

我现在使用的方法是“即时语法高亮”,我只高亮显示可见部分的正文。因此高亮显示的速度跟文件的大小根本是无关的。无论是多大的文件,在某一时刻只有一小部分是可见的。

怎么样实现?答案很简单:

  1. 子类化RichEdit控件并在你自己的窗口处理函数中处理 WM_PAINT 消息。
  2. 当收到 WM_PAINT 消息时,它调用RichEdit控件原来的窗口过程,让它正常地更新屏幕。
  3. 之后,我们将要高亮显示的词用不同的颜色来覆盖掉。

当然了,路也不是这么容易走的:仍然有两个次要的问题需要矫正,不过上面的方法工作起来很好。显示速度令人很满意。

现在让我们集中在细节上。子类化处理是很简单的,不需要很多注意力。真正复杂的部分是:我们必须找到一个快速的方法来搜索那些需要高亮的词。更复杂的那些在某个注释块里的 不 需要高亮显示的词。

我使用的方法可能不是最好的,但是它工作的很好。我敢肯定你可以找到更快的方法。不管怎么说,先看看我下面的方法:

  • 我创建一个有256元素的双字(DWORD)数组,全部初始化为0。每一个元素对应一个可能的 ASCII 字符,数组名叫 ASMSyntaxArray。例如,第21个元素代表ASCII 20h (空格字符)。我将他们作为快速查询表使用:譬如,假定我有一个词 "include",我从词中分离出第一个字符 (i) ,并以响应索引查找数组。如果该元素为0,我就立刻知道需要高亮的词是没有以 "i" 开头的。如果该元素非0,它就包含一个指针,指向一个 WORDINFO 结构的链表。里面包含了需要高亮词的信息。
  • 我读取需要高亮显示的词,并为每个词创建一个 WORDINFO 结构。
			WORDINFO struct 				WordLen dd ? 		; 词的长度,用来快速比较				pszWord dd ? 	       ; 词的指针				pColor dd ? 		; 用来高亮显示的颜色所在的DWORD的指针				NextLink dd ? 		; 下一个 WORDINFO 结构			WORDINFO ends                     

正如你所看到的,我使用词的长度来作为第二个快速比较方法。如果词中的第一个字符匹配后,我们下一个比较的是词的才长度。ASMSyntaxArray 中的每一个元素包含了一个指针,指向一个相关的WORDINFO 数组.例如,代表字符 "i" 的元素将会包含一个指向以"i"开头的词的链表。 pColor 成员指向一个DWORD,包含用来做高亮显示该词的颜色值。pszWord 指向要高亮显示的词。是小写形式的。

  • 链表的内存是从堆(heap)中分配的,速度快,容易清除,也就是说根本不用清楚。

高亮词列表保存在文件 "wordfile.txt"中,我通过 GetPrivateProfileString API 函数来访问。我提供了多达10种不同的语法颜色,从 C1 到 C10。颜色数组名叫 ASMColorArray。每一个 WORDINFO 结构的 pColor 成员都指向 ASMColorArray 中的某一个元素。因此闲时很容易改变语法颜色:你只需要改变 ASMColorArray 中的元素的值,这样所有使用那种颜色高亮的词就立刻使用新颜色显示。

例子

点此下地完整文件

------分隔线----------------------------
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
最新评论 查看所有评论
发表评论 查看所有评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 密码: 验证码:
推荐内容