RichTextBox实现关键字自定义颜色显示

现在的很多编辑工具都能实现代码中关键字的高亮显示,自己一时好玩也就随便写了一个:

首先建立一个XML文件:csharp.xml

<?xml version="1.0" encoding="utf-8" ?>
<definition name="C#" caseSensitive="true">
<word color="BLUE">private</word>
<word color="BLUE">protected</word>
<word color="BLUE">public</word>
<word color="BLUE">namespace</word>
<word color="BLUE">class</word>
<word color="BLUE">for</word>
<word color="BLUE">if</word>
<word color="BLUE">else</word>
<word color="BLUE">while</word>
<word color="BLUE">switch</word>
<word color="BLUE">case</word>
<word color="BLUE">using</word>
<word color="BLUE">get</word>
<word color="BLUE">return</word>
<word color="BLUE">null</word>
<word color="BLUE">void</word>
<word color="BLUE">int</word>
<word color="BLUE">string</word>
<word color="BLUE">float</word>
<word color="BLUE">char</word>
<word color="BLUE">this</word>
<word color="BLUE">set</word>
<word color="BLUE">new</word>
<word color="BLUE">true</word>
<word color="BLUE">false</word>
<word color="BLUE">const</word>
<word color="BLUE">static</word>
<word color="BLUE">internal</word>
<word color="BLUE">extends</word>
<word color="BLUE">super</word>
<word color="BLUE">import</word>
<word color="BLUE">default</word>
<word color="BLUE">break</word>
<word color="BLUE">try</word>
<word color="BLUE">catch</word>
<word color="BLUE">finally</word>
<word color="CadetBlue">Main</word>
<word color="CadetBlue">WriteLine</word>
<word color="CadetBlue">Console</word>
<word color="CadetBlue">WriteLine</word>
<word color="DarkOrange">;</word>
<register>printf</register>
</definition>

其中color指定了该关键字的颜色.

然后在VS中新建一工程,添加下面的这个类:

using System;
using System.Xml;
using System.IO;
using System.Collections;
using System.Reflection;
using System.Drawing;

namespace WindowsApplication1
{
    
    public class Parser
    {
        private XmlDocument xd=null; 
        private ArrayList al=null; //对xml流解析后,会把每一个关键字字符串放入这个容器中
        private bool caseSensitive=false; //记录当前语言大小写敏感否
        private ArrayList cl=null;//对xml流解析后,把每一个C关键字颜色保留
        
        
        
        internal Parser(SyntaxEditor.Languages language) //构造函数接受一个枚举变量
        {            
            Assembly asm = Assembly.GetExecutingAssembly();
            string filename="";
            switch(language) //取得xml文件名
            {
                case SyntaxEditor.Languages.CSHARP:
                    filename="csharp.xml";
                    break;
                case SyntaxEditor.Languages.JSHARP:
                    filename="jsharp.xml";
                    break;
                case SyntaxEditor.Languages.SQL:
                    filename="sql.xml";
                    break;
                case SyntaxEditor.Languages.VBSCRIPT:
                    filename="vbscript.xml";
                    break;
                default:
                    break;
            }
        
            StreamReader reader= new StreamReader(filename,
        System.Text.Encoding.UTF8
); //下面的代码解析xml流

            xd=new XmlDocument();
            xd.Load(reader);

            al=new ArrayList();
            cl=new ArrayList();
            XmlElement root=xd.DocumentElement;

            XmlNodeList xnl=root.SelectNodes("/definition/word");
            for(int i=0;i<xnl.Count;i++)
            {  
                al.Add(xnl[i].ChildNodes[0].Value); //将关键子收集到al
                cl.Add(xnl[i].Attributes["color"].Value);//收集关键字的颜色
                
            }
            //检测是否判断大小写
            this.caseSensitive=bool.Parse(root.Attributes["caseSensitive"].Value);

        }

        public Color IsKeyWord(string word ) //判断字符串是否为关键字
        {
            
            for(int i=0;i<al.Count;i++)
            {
                if(string.Compare(word,al[i].ToString(),!caseSensitive)==0)
                {
                    string ColorTemp=(cl[i].ToString()!=string.Empty?cl[i].ToString():"Black");                    
                    Color c;
                    try
                    {
                         c=Color.FromName(ColorTemp);
                    }
                    catch (Exception e)
                    {
                         c=Color.Black;
                    }
                    return c;                    
                }
            }
            
            return Color.Black;

        }

    }
}

 

然后新建一用户控件继承RichTextBox

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using HWND = System.IntPtr;

namespace WindowsApplication1
{
    /// <summary>
    /// SyntaxEditor 的摘要说明。
    /// </summary>
    public class SyntaxEditor :System.Windows.Forms.RichTextBox
    {        
        /// <summary> 
        /// 必需的设计器变量。

        /// </summary>
        private System.ComponentModel.Container components = null;    
        int line;
        private Parser parser;
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        //使用win32api:SendMessage来防止控件着色时的闪烁现象
        [DllImport("user32")] private static extern int SendMessage(HWND hwnd, int wMsg, int wParam, IntPtr lParam);
        private const int WM_SETREDRAW = 0xB;
        public SyntaxEditor()
        {
            // 该调用是 Windows.Forms 窗体设计器所必需的。
            InitializeComponent();
            base.WordWrap=false;
            // TODO: 在 InitComponent 调用后添加任何初始化

            
        }
        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if( components != null )
                    components.Dispose();
            }
            base.Dispose( disposing );
        }
        #region 组件设计器生成的代码
        /// <summary>
        /// 设计器支持所需的方法 - 不要使用代码编辑器 
        /// 修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {        
            this.Name = "SyntaxEditor";
            
        }
        #endregion
        //重写基类的OnTextChanged方法。为了提高效率,程序是对当前文本插入点所在行进行扫描,
        //以空格为分割符,判断每个单词是否为关键字,并进行着色。
        protected override void OnTextChanged(EventArgs e) 
        {
            if(base.Text!="")
            {
                int selectStart=base.SelectionStart;
                line=base.GetLineFromCharIndex(selectStart);
                string lineStr=base.Lines[line];
                int linestart=0;
                for(int i=0;i<line;i++)
                {
                    linestart+=base.Lines[i].Length+1;
                }

                SendMessage(base.Handle, WM_SETREDRAW, 0, IntPtr.Zero);
                
                base.SelectionStart=linestart;
                base.SelectionLength=lineStr.Length;
                base.SelectionColor=Color.Black;
                base.SelectionStart=selectStart;
                base.SelectionLength=0;
                
                //对一行字符串用空格或者.分开
                string[] words=lineStr.Split(new char[]{' ','.','\n','(',')','}','{','"','[',']'});                
                parser=new Parser(this.language);

                for(int i=0;i<words.Length;i++)//一个字符段一个字符段来判断
                {
                    
                    //判断是否是程序保留字 是的话高亮显示
                    if(parser.IsKeyWord(words[i])!=Color.Empty)
                    { 
                        int length=0;
                        for(int j=0;j<i;j++)
                        {
                            length+=words[j].Length; 
                        }
                        length+=i;
                        int index=lineStr.IndexOf(words[i],length);


                        base.SelectionStart=linestart+index;
                        base.SelectionLength=words[i].Length;
                        //base.SelectionFont
                        base.SelectionColor=parser.IsKeyWord(words[i]);
                        

                        base.SelectionStart=selectStart;
                        base.SelectionLength=0;
                        base.SelectionColor=Color.Black;
                    }


                }
                SendMessage(base.Handle, WM_SETREDRAW, 1, IntPtr.Zero);
                base.Refresh();
            }
            base.OnTextChanged (e);
        }

        public new bool WordWrap
        {
            get{return base.WordWrap;}
            set{ base.WordWrap=value;}
        }

        public enum Languages
        {
            SQL,
            VBSCRIPT,
            CSHARP,
            JSHARP
        }

        private Languages language=Languages.CSHARP;
        
        public Languages Language
        {
            get{return this.language;}
            set{this.language=value;}
        }

    }
}

 

这个时候你只要保证XML文件和exe或者数据集(如果你打算这样做)在同一个目录就可以了,看看吧下面就是测试效果:

呵呵 很简单哦,看样子写个C语言编辑环境也不是很难哦 呵呵~

我尝试去掉API在MONO上面编译,可惜MONO并没有支持RichTextBox控件,既然只能在Win上面运行,所以还是加上API好了,可以减少屏幕闪动感觉.



转载:: http://tb.blog.csdn.net/TrackBack.aspx?PostId=549896

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值