语法高亮
http://eros-hr.iteye.com/blog/663712?page=3#comments
相信使用过visual studio的人都会对其编辑器所支持的“代码语法高亮显示(syntax highlight)”功能留下难忘的印象。
我记得我本科毕业设计时就想着设计一个自己的语法高亮编辑器,但是一直不知道人家是怎么实现的,实现原理是什么。一直到现在都没有弄清楚。一个支持语法高亮的Editor控件,主要有两个技术难点:1> 哪个词该高亮?该用什么颜色高亮? 2>怎么在黑白的TextBox中用不同的颜色显示不同的词? 第一个问题其实是属于语法解析的范畴,在编译原理中有涉及到的。使用lex&&yacc做语法解析器就完全可以识别出哪些是keyword,哪些是function name,哪些是字符串,哪些是constant变量,哪些是变量名的。我脑海中的真正难点是第二个难点。因为我之前接触过的TextBox只支持一种颜色,你要设置成红色,那所有的内容就都是红色。所以我一直不理解人家是怎么做到让不同的字显示成不同的颜色的。
今天看到了GNU source-highlight这个库(http://www.gnu.org/software/src-highlite/),所以又想起了这个问题,晚上在google.com上搜了一番,还真找到了想要的答案。
我就不再介绍具体的实现细节了,只是简单描述一下到底是怎么回事,然后把原文的地址附在末尾,有兴趣的朋友可以自己去阅读原文。呵呵,其实我只是对它的实现好奇,想弄懂它的实现原理,但是不可能有精力去写一个这样的软件。好了,开始正式讲了:
★ 1. 常见的支持Syntax Highlight的编辑器,并不会用lex&&yacc这样一套复杂的重量级工具。基本上都是用正则表达式来识别不同的语法成分。比如上面提到的GNU Source-Highlight库,底层实际上就是一组正则表达式。
★ 2. TextBox控件的确是只支持一种颜色,但是要知道还有一个更强大的控件叫RichTextBox。RichTextBox支持不同的word用不同的颜色显示。
★ 3. 实时编辑、实时高亮显示的问题:用户每敲入一个字符你就把整个文档都重新highlight一遍吗?哦……你会说,我只重新高亮用户正在编辑的这一行。嗯,不错的思路。但是由于你每高亮一个word,就会导致屏幕repaint一次,一行中有100个word的话,用户每敲入一个字符,你就会对这一行数据repaint 100次,屏幕会不停地闪烁。大哥,这可是不行啊,你想把我炼成火眼金睛啊?? 为了解决闪烁的问题,有两个思路,一种就是禁止掉系统自动的Repaint,等highlight结束后,你统一用InvalidRect API把需要repaint的矩形区域“invalidate(置无效)”一下,系统就会自动更新并repaint,把你新的hightlight效果render(渲染)出来。当然,要实现这一点,还有别的办法,比如通过截获系统WM_PAINT消息的途径,也就是说,在你开始highlight当前行时,屏蔽掉WM_PAINT,等highlight完当前行的时候,你再把WM_PAINT打开,这样repaint一次就可以了。第二种思路呢?就是在程序内部,记录下用户每次敲入一个字符前后,有哪些word的颜色需要修改,哪些word的颜色不用动,这样你只需要repaint那些需要改动的word就行了。总之,尽可能地减少repaint的次数就可以缓轻闪烁的问题。就解决flickering(闪烁)问题,google一下,有大量的文章。
我看了觉得比较不错的三篇文章是:
1. Syntax Highlighting in Rich TextBox Control - Part 1
2. Syntax Highlighting in RichTextBox Control - Part 2
3. Syntax Highlighting in RichTextBox using C#
http://www.c-sharpcorner.com/UploadFile/kirtan007/2511/
前两篇文章中还带有原作者的实例代码,相信会对大家有用。