RichTextBox着色与着色不闪

近来写的一个数据查询分析器意外的快捷,不到两晚工夫就搞定了。完成度相当的高。当然少不了关键字着色,不过着色的代码来自的网上,看了一下感觉过多的循环

//文本框改变事件    
            int index = this.richTextBox1.SelectionStart;  //记录修改的位置           
            string[] keystr ={ "select ", "from ", "where ", " and ", " or ", " order ", " by ", " desc ", " when ", " case ",
  " then ", " end ", " on ", " in ", " is ", " as ", " else ", "left ", " join ", " not ", " null "," like "," exists " };
            for (int i = 0; i < keystr.Length; i++)
                this.getbunch(keystr[i], this.richTextBox1.Text, Color.Blue);


public int getbunch(string p, string s,Color pColor) //给关键字上色
        {
            int cnt = 0; int M = p.Length; int N = s.Length;
            char[] ss = s.ToCharArray(), pp = p.ToCharArray();
            if (M > N) return 0;
            for (int i = 0; i < N - M + 1; i++)
            {
                int j;
                for (j = 0; j < M; j++)
                {
                    if (ss[i + j] != pp[j]) break;
                }
                if (j == p.Length)
                {
                    this.richTextBox1.Select(i, p.Length);
                    this.richTextBox1.SelectionColor = pColor;
                    cnt++;
                }
            }
            return cnt;
        }

且关键字的边界也没有处理好。于是重新组织了判断关键字的代码,总的流程是先记录所有关键字及其所用颜色。从头到到尾取出每一个单词着色,以下是主体代码

/// <summary>
/// 着色
/// </summary>
public void RunColor()
{
    this.BeginUpdate();//停止绘制
    //文本框改变事件    
    int lastIndex = this.SelectionStart;  //记录修改的位置
    
    int index =0;
    int wordStart=-1;//找到的单词开始位置
    char[] text = this.Text.ToCharArray();//打散每一个字符
    StringBuilder sb = new StringBuilder();
    //尝试取出每一个单词
    while(index<text.Length)
    {
        char chk = text[index];
        if (WhiteSpaceChars.Contains(chk))//是否空白字符
        {
            if (wordStart >= 0)
            {
                //取出单词
                string code = sb.ToString();
                colorWords(code.ToLower(), wordStart);
                wordStart = -1;
            }
            else
            {
                //空白字符,未找到词开头,不需作任何处理
            }
        }
        else
        {
            //找到非空白字符
            if (wordStart == -1)//找到词开头了。
            {
                sb = new StringBuilder();
                wordStart = index;
            }
            sb.Append(chk);
        }
        index++;//下一字符
    }
    if (sb.Length > 0 && wordStart>=0)//最后一个词
    {
        string code = sb.ToString();
        colorWords(code.ToLower(),wordStart);
    }
    this.Select(lastIndex, 0);  //返回修改的位置
    this.SelectionColor = Color.Black;
    this.EndUpdate();//恢复绘制事件            
}

以下是完整的RichTextbox的代码,解决着色不闪。着色方法RunColor需要外部调用,控件不会自动着色。

public class MyRichTextBox : RichTextBox
    {
        //private class paintHelper : Control
        //{
        //    public void DefaultWndProc(ref Message m)
        //    {
        //        this.DefWndProc(ref m);
        //    }
        //}

        private const int WM_PAINT = 0x000F;
        private int lockPaint;
        private bool needPaint;        
        //private paintHelper pHelp = new paintHelper();

        public void BeginUpdate()
        {            
            lockPaint++;
        }

        public void EndUpdate()
        {            
            lockPaint--;
            if (lockPaint <= 0)
            {
                lockPaint = 0;
                if (needPaint)
                {
                    this.Refresh();
                    needPaint = false;
                }
            }
        }

        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case WM_PAINT:                   
                    if (lockPaint <= 0)
                    {
                        base.WndProc(ref m);
                    }
                    else
                    {
                        needPaint = true;
                        //pHelp.DefaultWndProc(ref m);
                    }
                    return;
            }

            base.WndProc(ref m);
        }

        
        Dictionary<string, Color> words = new Dictionary<string, Color>();
        /// <summary>
        /// 设置字符颜色
        /// </summary>
        /// <param name="pWords">关键字</param>
        /// <param name="pColor">所用颜色</param>
        /// <param name="isKeyWord">真时,替换之前设置的颜色。否的话,如果已设置相关关键字,忽略该设置</param>
        public void SetColorWord(IEnumerable<string> pWords, Color pColor,bool isKeyWord)
        {
            foreach (string one in pWords)
            {
                string low = one.ToLower();
                if (words.ContainsKey(low))
                {
                    if (isKeyWord)
                        words[low] = pColor;
                }
                else
                {
                    words.Add(low, pColor);
                }
            }
        }       
        /// <summary>
        /// 着色
        /// </summary>
        public void RunColor()
        {
            this.BeginUpdate();//停止绘制
            //文本框改变事件    
            int lastIndex = this.SelectionStart;  //记录修改的位置
            
            int index =0;
            int wordStart=-1;//单词的开始位置
            char[] text = this.Text.ToCharArray();//打散每一个字符
            StringBuilder sb = new StringBuilder();
            //尝试取出每一个单词
            while(index<text.Length)
            {
                char chk = text[index];
                if (WhiteSpaceChars.Contains(chk))//是否空白字符
                {
                    if (wordStart >= 0)//空白字符,前面已找到单词的开始位置,这就是单词的结束了
                    {
                        //取出音词
                        string code = sb.ToString();
                        colorWords(code.ToLower(), wordStart);
                        wordStart = -1;
                    }
                    else
                    {
                        //空白字符,未找到词开头,不需作任何处理
                    }
                }
                else
                {
                    //找到非空白字符
                    if (wordStart == -1)//找到词开头了。
                    {
                        sb = new StringBuilder();
                        wordStart = index;
                    }
                    sb.Append(chk);
                }
                index++;//下一字符
            }
            if (sb.Length > 0 && wordStart>=0)//最后一个词
            {
                string code = sb.ToString();
                colorWords(code.ToLower(),wordStart);
            }
            this.Select(lastIndex, 0);  //返回修改的位置
            this.SelectionColor = Color.Black;
            this.EndUpdate();//恢复绘制事件            
        }
        /// <summary>
        /// 给单词着色,非关键字改为黑色
        /// </summary>
        /// <param name="pChkWord"></param>
        /// <param name="pStart"></param>
        private void colorWords(string pChkWord,int pStart)
        {
            this.Select(pStart, pChkWord.Length);
            if (words.ContainsKey(pChkWord))
                this.SelectionColor = words[pChkWord];
            else
                this.SelectionColor = Color.Black;
        }
        /// <summary>
        /// 空白字符
        /// </summary>
        public static readonly char[] WhiteSpaceChars = new char[] { (char)0x00, (char)0x01, (char)0x02, (char)0x03, (char)0x04, (char)0x05, 
            (char)0x06, (char)0x07, (char)0x08, (char)0x09, (char)0x0a, (char)0x0b, (char)0x0c, (char)0x0d, (char)0x0e, (char)0x0f, 
            (char)0x10, (char)0x11, (char)0x12, (char)0x13, (char)0x14, (char)0x15, (char)0x16, (char)0x17, (char)0x18, (char)0x19, (char)0x20,
            (char)0x1a, (char)0x1b, (char)0x1c, (char)0x1d, (char)0x1e, (char)0x1f, (char)0x7f, (char)0x85, (char)0x2028, (char)0x2029 };
    }

 

posted @ 2016-09-22 18:23  生命体验之kevin-Y  阅读(887)  评论(0编辑  收藏  举报