技術文章 > 用C#實現的語法高亮控件

用C#實現的語法高亮控件

2020-02-27 13:48

文檔管理軟件,文檔管理系統,知識管理系統,檔案管理系統的技術資料:
因為工作需要,用c#實現了一個能夠對vbscript,c#,j#,sql顯示語法高亮的文本編輯控件。這里詳細介紹一下它的原理。
該控件是從RichTextBox繼承下來,以xml格式存儲各種語言的關鍵字。然后重寫RichTextBox的OnTextChanged方法,在該方法中對輸入文本進行解析,并對關鍵字進行著色。源代碼點擊這里下載。
xml文件格式如下,這里僅以j#為例。caseSensitive代表該語言是否大小寫敏感。當然,由于本人懶惰成性,關鍵字是從網上搜集別人整理好的,如有遺漏,概不負責:)
如果需要解析其他語言,請添加相應的xml文件,并修改枚舉類型Languages以及Parser類的構造函數中的相應代碼。已知bug:當兩個詞是由括號分割的時候,程序無法識別。比如Function foo(integer i),程序會把foo(integer當作一個詞。當然這里有兩個解決辦法,一個是程序自動進行語法排版,在括號前后自動插入空格;另一個是對括號進行解析。也許以后有空的時候我會加上。
復制 保存

private
protected
public
namespace
class
var
for
if
else
while
switch
case
using
get
return
null
void
int
string
float
this
set
new
true
false
const
static
package
function,
internal
extends
super
import
default
break
try
catch
finally
+
-
=


private
protected
public
namespace
class
var
for
if
else
while
switch
case
using
get
return
null
void
int
string
float
this
set
new
true
false
const
static
package
function,
internal
extends
super
import
default
break
try
catch
finally
+
-
=

Parser類是負責對xml流進行解析,并包含一個方法來判斷一個字符串是不是關鍵字。詳細的代碼和注釋如下:
復制 保存using System;
[code]
csharp
using System.Xml;
using System.IO;
using System.Collections;
using System.Reflection;
namespace SyntaxEditor
{
///
/// Parser 的摘要說明。
///

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;
}
}
}
[/code]
控件類代碼如下。
復制 保存using System;
[code]
csharp
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
{
///
/// UserControl1 的摘要說明。
///

public class SyntaxEditor : System.Windows.Forms.RichTextBox
{
///
/// 必需的設計器變量。
///

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 調用后添加任何初始化
}
///
/// 清理所有正在使用的資源。
///

protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
components.Dispose();
}
base.Dispose(disposing);
}
#region 組件設計器生成的代碼
///
/// 設計器支持所需的方法 - 不要使用代碼編輯器
/// 修改此方法的內容。
///

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; }
}
}
}
[/code]
体彩7星彩规则 基金配资条件 太仓股票配资电话 航宇汇金 闪电配资 微策略配资 德宏信投 鑫鑫配资 翻翻配配资 中国主要股票指数 道琼斯工业股票指数是什么意思 佳人期货配资公司 什么叫融资 股票配资是什么 什么股票配资平台靠谱 股票分析软件排行榜 股票分析软件哪个好 三明期货配资