用c#实现的语法高亮控件

用c#实现了一个能够对vbscript,c#,j#,sql显示语法高亮的文本编辑控件。这里详细介绍一下它的原理。

该控件是从RichTextBox继承下来,以xml格式存储各种语言的关键字。然后重写RichTextBox的OnTextChanged方法,在该方法中对输入文本进行解析,并对关键字进行着色。源代码点击这里下载。

xml文件格式如下,这里仅以j#为例。caseSensitive代表该语言是否大小写敏感。当然,由于本人懒惰成性,关键字是从网上搜集别人整理好的,如有遗漏,概不负责:)

如果需要解析其他语言,请添加相应的xml文件,并修改枚举类型Languages以及Parser类的构造函数中的相应代码。已知bug:当两个词是由括号分割的时候,程序无法识别。比如Function foo(integer i),程序会把foo(integer当作一个词。当然这里有两个解决办法,一个是程序自动进行语法排版,在括号前后自动插入空格;另一个是对括号进行解析。也许以后有空的时候我会加上。

<?xml version="1.0" encoding="utf-8" ?>
<definition name="J#" caseSensitive="true">
 <word>private</word>
 <word>protected</word>
 <word>public</word>
 <word>namespace</word>
 <word>class</word>
 <word>var</word>
 <word>for</word>
 <word>if</word>
 <word>else</word>
 <word>while</word>
 <word>switch</word>
 <word>case</word>
 <word>using</word>
 <word>get</word>
 <word>return</word>
 <word>null</word>
 <word>void</word>
 <word>int</word>
 <word>string</word>
 <word>float</word>
 <word>this</word>
 <word>set</word>
 <word>new</word>
 <word>true</word>
 <word>false</word>
 <word>const</word>
 <word>static</word>
 <word>package</word>
 <word>function,</word>
 <word>internal</word>
 <word>extends</word>
 <word>super</word>
 <word>import</word>
 <word>default</word>
 <word>break</word>
 <word>try</word>
 <word>catch</word>
 <word>finally</word>
 <word>+</word>
 <word>-</word>
 <word>=</word>
</definition>

Parser类是负责对xml流进行解析,并包含一个方法来判断一个字符串是不是关键字。详细的代码和注释如下:

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

namespace SyntaxEditor
{
 /// <summary>
 /// Parser 的摘要说明。
 /// </summary>
 public class Parser
 {
  private  XmlDocument xd=null;    
  private  ArrayList al=null;    //对xml流解析后,会把每一个关键字字符串放入这个容器中
  private bool caseSensitive=false;    //记录当前语言大小写敏感否

  internal Parser(SyntaxEditor.Languages language)    //构造函数接受一个枚举变量
  {
   //
   // TODO: 在此处添加构造函数逻辑
   //
     
   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;
   }

   Stream strm = asm.GetManifestResourceStream(asm.GetName().Name + "."+filename);    //取得xml流

   //Reads the contents of the embedded file.
   StreamReader reader= new StreamReader(strm);    //下面的代码解析xml流
   
   xd=new XmlDocument();
   xd.Load(reader);
   
   al=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); 
   }
   

   this.caseSensitive=bool.Parse(root.Attributes["caseSensitive"].Value);
   
  }

  public bool IsKeyWord(string word)    //判断字符串是否为关键字
  {
   bool rtn=false;
   for(int i=0;i<al.Count;i++)
   {
    if(string.Compare(word,al[i].ToString(),!caseSensitive)==0)
    {
     rtn=true;
     break;
    }
   }
   return rtn;
   
  }
 }
}

控件类代码如下。


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 SyntaxEditor
{
 /// <summary>
 /// UserControl1 的摘要说明。
 /// </summary>
 public class SyntaxEditor : System.Windows.Forms.RichTextBox
 {
  /// <summary>
  /// 必需的设计器变量。
  /// </summary>
  private System.ComponentModel.Container components = null;

//使用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()
  {
   //
   // SyntaxEditor
   //
   this.Name = "SyntaxEditor";

  }
  #endregion

 //重写基类的OnTextChanged方法。为了提高效率,程序是对当前文本插入点所在行进行扫描,

//以空格为分割符,判断每个单词是否为关键字,并进行着色。

  protected override void OnTextChanged(EventArgs e)   
  {
   if(base.Text!="")
   {
    int selectStart=base.SelectionStart;
    int 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[]{' '});
    Parser parser=new Parser(this.language);
    for(int i=0;i<words.Length;i++)
    {
     if(parser.IsKeyWord(words[i]))
     { 
      
      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.SelectionColor=Color.Blue;
      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;}
  }

  public enum Languages
  {
   SQL,
   VBSCRIPT,
   CSHARP,
   JSHARP
  }
  
  private Languages language=Languages.SQL;

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

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在一个TextBox中实现C++语法高亮,可以通过以下步骤实现: 1. 在TextBox的TextChanged事件中获取文本框中的文本。 2. 使用正则表达式匹配C++语法中的关键字、注释、字符串等。 3. 为匹配到的文本设置不同的颜色。 以下是一个简单的示例代码,可以实现关键字和注释的高亮: ```csharp private void textBox1_TextChanged(object sender, EventArgs e) { string syntax = @"(\b(abstract|as|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|do|double|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|goto|if|implicit|in|int|interface|internal|is|lock|long|namespace|new|null|object|operator|out|override|params|private|protected|public|readonly|ref|return|sbyte|sealed|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|virtual|void|volatile|while)\b)|(\/\/.*)"; MatchCollection matches = Regex.Matches(textBox1.Text, syntax, RegexOptions.Multiline); int startIndex = textBox1.SelectionStart; int length = textBox1.SelectionLength; foreach (Match match in matches) { textBox1.Select(match.Index, match.Length); textBox1.SelectionColor = Color.Blue; } textBox1.Select(startIndex, length); } ``` 需要注意的是,这个示例代码只是一个简单的实现,还有很多C++语法的特性没有考虑到。如果需要完整的C++语法高亮支持,可以考虑使用专业的文本编辑器控件,比如Scintilla。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值