(改进的)快速语法高亮控件!
语法高亮从未如此简单!
介绍
大家好,CodeProject!我又回来了。这次我删除了之前的文章,那是我写的第一篇文章,内容非常复杂冗长,现在我终于改进了代码。据我所知,现在已经没有 bug 了,控件的速度大约提高了 35-45%。如果你没看过我之前的文章,那么,基本上,这是一个我自己编写的语法高亮控件。它派生自 RichTextBox
,我想大家已经看过很多人制作的类似控件了。不过不用担心,我保证这个控件能够满足任何需求(难道不是一样的吗?:P)。
代码
我将提供的这段代码完全由我自己编写。灵感来源于许多记事本(Notepad++、Visual Studio 的 IDE)。这是一个基本的代码,任何能够理解这段简单代码的人都应该能够轻松地做任何想做的事情。如果您使用此控件,请确保将其用于好的用途,我不需要任何(署名?),因为这纯粹是为了我自己的学习目的而制作的。
如何使用代码?
- 创建一个新项目或使用现有项目。
- 通过转到解决方案资源管理器,添加,新建项,类来添加一个新类。
- 将类代码替换为以下内容。
- 生成或调试应用程序。
- (拖动)(创建)(在)
TextBox
(中)(或创建一个)(通过)(代码)(在工具箱中)。 - 成功!
代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Drawing;
using System.Threading;
namespace Classik
{
public class AdvancedRichTextBox : RichTextBox
{
#region API Stuff
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetScrollPos(IntPtr hWnd, int nBar);
[DllImport("user32.dll")]
public static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);
[DllImport("user32.dll")]
public static extern bool LockWindowUpdate(IntPtr hWnd);
private const int SB_HORZ = 0x0;
private const int SB_VERT = 0x1;
#endregion
public int HorizontalPosition
{
get { return GetScrollPos((IntPtr)this.Handle, SB_HORZ); }
set { SetScrollPos((IntPtr)this.Handle, SB_HORZ, value, true); }
}
public int VerticalPosition
{
get { return GetScrollPos((IntPtr)this.Handle, SB_VERT); }
set { SetScrollPos((IntPtr)this.Handle, SB_VERT, value, true); }
}
public AdvancedRichTextBox()
{
this.ForeColor = Color.Black;
}
int PreviousLength = 0;
protected override void OnTextChanged(EventArgs e)
{
if (PreviousLength == this.Text.Length - 1 || PreviousLength == this.Text.Length + 1)
SyntaxView(new Regex("( for | while )"));
else
SyntaxAll(new Regex("( for | while )"));
PreviousLength = this.Text.Length;
base.OnTextChanged(e);
}
public void SyntaxView(Regex Syntax)
{
int SelectionStart = this.SelectionStart;
int SelectionLength = this.SelectionLength;
int FirstCharacter = this.GetCharIndexFromPosition(new Point(0, 0));
int FirstLine = this.GetLineFromCharIndex(FirstCharacter);
int LastLine = this.GetLineFromCharIndex(this.GetCharIndexFromPosition(
new Point(this.ClientSize.Width, this.ClientSize.Height))) ;
Color SelectionColor = this.ForeColor;
Font SelectionFont = this.Font;
for (int i = FirstLine; i <= LastLine; i++)
{
MatchCollection Matches = Syntax.Matches(this.Lines[i]);
if (Matches.Count > 0)
{
LockWindowUpdate(this.Handle);
foreach (Match m in Matches)
{
int Start = this.GetFirstCharIndexFromLine(i);
this.Select(Start + m.Index, m.Length);
this.SelectionColor = Color.Red;
}
}
}
this.SelectionStart = SelectionStart;
this.SelectionLength = SelectionLength;
this.SelectionColor = SelectionColor;
this.SelectionFont = SelectionFont;
LockWindowUpdate(IntPtr.Zero);
this.Invalidate();
}
public void SyntaxAll(Regex Syntax)
{
int SelectionStart = this.SelectionStart;
int SelectionLength = this.SelectionLength;
Color SelectionColor = this.ForeColor;
Font SelectionFont = this.Font;
LockWindowUpdate(this.Handle);
for (int i = 0; i < this.Lines.Length; i++)
{
MatchCollection Matches = Syntax.Matches(this.Lines[i]);
if (Matches.Count > 0)
{
LockWindowUpdate(this.Handle);
foreach (Match m in Matches)
{
int Start = this.GetFirstCharIndexFromLine(i);
this.Select(Start + m.Index, m.Length);
this.SelectionColor = Color.Red;
}
}
}
this.SelectionFont = SelectionFont;
this.SelectionColor = SelectionColor;
this.SelectionStart = SelectionStart;
this.SelectionLength = SelectionLength;
LockWindowUpdate(IntPtr.Zero);
this.Invalidate();
}
}
}
使用代码
现在,我们如何使用这个高亮工具呢?我已经制作了一些简单的步骤“代码”框,它将解释如何添加代码并使用它。但是!还有一些其他的事情,主要是,如何添加更多高亮显示呢!很简单。我们有两个 voids,SyntaxView
和 SyntaxAll
。为了使它工作,它们都需要更改。您只需要专注于
LockWindowUpdate(this.Handle);
foreach (Match m in Matches)
{
int Start = this.GetFirstCharIndexFromLine(i);
this.Select(Start + m.Index, m.Length);
this.SelectionColor = Color.Red;
}
和
SyntaxView(new Regex("( for | while )"));
else
SyntaxAll(new Regex("( for | while )"));
最小的一个应该能自己解释清楚。如果不能,基本上,每个你想高亮显示的词都需要在新的 Regex 中,用 '|' 分隔。上面的代码在两个 void 中都有。它可以用来改变高亮显示的颜色。您还可以使用 'this.SelectionFont
' 更改字体。您可能还会想知道:“如何添加更多颜色,而不是只有一种颜色”,这也很容易。您只需向两个 foreach
循环添加一个小的 Switch 或 if 语句,如下所示:
Color HighlightColor = Color.Blue;
switch (m.ToString())
{
case "one":
HighlightColor = Color.Blue;
break;
case "two":
HighlightColor = Color.Orange;
break;
case "three":
HighlightColor = Color.Purple;
break;
}
this.SelectionColor = HighlightColor ;
当然,还有很多其他的方法可以做到这一点。这只是一个简单的例子。但请确保同时更改 view 和 all。
关注点
我认为本文最有趣的部分是它易于使用,并且易于大家理解。
其他说明
有一些外部 API voids,其中一些应该能自己解释清楚,但有一个不能
LockWindowUpdate
:这会使窗口冻结,直到使用 'IntPtr.Zero
' 解冻。你使用句柄来完成这个操作。
如果有人在阅读本文时遇到问题,我深感抱歉,英语不是我的母语,所以我希望这篇文章既有趣又特别容易理解。
历史
- 修复了旧版本中已知的每个错误。
- 2013 年 1 月 2 日:修复了“foreach 中的高亮显示”错误。感谢 wvd_vegt。