C#开发高亮语法编辑器(一)——TextBox ,RichTextBox

一、RichTextBox基本设置
二、实现语法高亮
三、关键字提示
四、实现行号

就简单快速得开发文本编辑器TextBox 最为简单,大家用得也多,缺点是无法实现复杂的操作。RichTextBox虽然是则功能比它强大很多。

单击显示全图,Ctrl+滚轮缩放图片

这里要实现以下功能的编辑器:

1、实现语法高亮;
2、关键字提示;
3、行号。

显然TextBox 无法完成我们的任务,虽然都派生自TextBoxBase,但就控制力而言RichTextBox比它优秀很多。这里选用RichTextBox尝试开发。

注:以下只讨论简单开发,不考虑复杂的关键字查找机制。


一、RichTextBox基本设置

这里先建立一个工程,建立窗体Form1。
可以简单添加RichTextBox控件,可以在Form1_Load中建立。代码如下:
复制   保存
this.WindowState = System.Windows.Forms.FormWindowState.Maximized;

RichTextBox rich = new RichTextBox();
rich.Multiline = true;
rich.Height = this.Height - 100;
rich.Width = this.Width - 100;
rich.Left = 40;
rich.Top = 40;
rich.WordWrap = true;
rich.Text = "12345678";
rich.ScrollBars = RichTextBoxScrollBars.ForcedVertical;
this.Controls.Add(rich);

这样就建立了简单的RichTextBox,宽度和高度都设置了。没有做Form1窗体缩放的处理。


二、实现语法高亮

在RichTextBox里实现语法高亮还是非常简单的。可以使用
复制   保存
rich.Select(0, 1);
rich.SelectionFont = new Font("宋体", 12, (FontStyle.Regular));
rich.SelectionColor = Color.Blue;

意思是,先选择第一个字母,按上面的设置,选择到了数字‘1’,然后设置这个字的字体大小,再设置字的颜色。

如果对关键字进行处理(这里只处理光标向后流动的情况)
首先添加输入事件
复制   保存
rich.KeyDown += new KeyEventHandler(rich_KeyDown);   //这一行添加到Form1_Load中

void rich_KeyDown(object sender, KeyEventArgs e)
{
 //throw new Exception("The method or operation is not implemented.");
}

建立关键字
复制   保存
public static List<string> AllClass()
{
    List<string> list = new List<string>();
    list.Add("function");
    list.Add("return");
    list.Add("class");
    list.Add("new");
    list.Add("extends");
    list.Add("var");
    return list;
}

当KeyDown事件发生时,向前查找
复制   保存
//返回搜索字符
public static string GetLastWord(string str, int i)
{
    string x = str;
    Regex reg = new Regex(@"/s+[a-z]+/s*", RegexOptions.RightToLeft);
    x = reg.Match(x).Value;

    Regex reg2 = new Regex(@"/s");
    x = reg2.Replace(x, "");
    return s;
}

复制   保存
void rich_KeyDown(object sender, KeyEventArgs e)
{
    RichTextBox rich = (RichTextBox) sender;
    //throw new Exception("The method or operation is not implemented.");
    string s = GetLastWord(rich.Text, rich.SelectionStart);

    if (AllClass().IndexOf(s) > -1)
    {
        MySelect(rich, rich.SelectionStart, s, Color.CadetBlue, true);
    }
}

复制   保存
//设定颜色
public static void MySelect(System.Windows.Forms.RichTextBox tb, int i, string s, Color c, bool font)
{
    tb.Select(i - s.Length, s.Length);
    tb.SelectionColor = c;
    //是否改变字体
    if (font)
        tb.SelectionFont = new Font("宋体", 12, (FontStyle.Bold));
    else
        tb.SelectionFont = new Font("宋体", 12, (FontStyle.Regular));
    //以下是把光标放到原来位置,并把光标后输入的文字重置
    tb.Select(i, 0);
    tb.SelectionFont = new Font("宋体", 12, (FontStyle.Regular));
    tb.SelectionColor = Color.Black;
}

这样就完成了高亮工作。


三、关键字提示

实现关键字提示也是在KeyDown中实现,在提示字种搜索GetLastWord返回的文字,如果前半部分匹配。那么就建立ListBox控件。
复制   保存
void tb_KeyDown(object sender, KeyEventArgs e)
{
    RichTextBox tb = (RichTextBox) sender;
    if (/*条件搜索到匹配字符*/)
    {
        //搜索ListBox是否已经被创建
        Control[] c = tb.Controls.Find("mylb", false);
        if (c.Length > 0)
            ((ListBox) c[0]).Dispose();  //如果被创建则释放

        ListBox lb = new ListBox();
        lb.Name = "mylb";
        lb.Items.Add("asdasdasd");
        lb.Items.Add("asdasdasd");
        lb.Items.Add("asdasdasd");
        lb.Items.Add("asdasdasd");
        lb.Items.Add("asdasdasd");
        lb.Items.Add("asdasdasd");
        lb.Items.Add("asdasdasd");
        lb.Show();
        lb.TabIndex = 100;
        lb.Location = tb.GetPositionFromCharIndex(tb.SelectionStart);
        lb.Left += 10;
        tb.Controls.Add(lb);
    }
}

当然,另外一面,如果创建ListBox,而又在RichTextBox 点击了鼠标也去释放。
复制   保存
void rich_MouseClick(object sender, MouseEventArgs e)
{
    RichTextBox tb = (RichTextBox) sender;
    Control[] c = tb.Controls.Find("mylb", false);
    if (c.Length > 0)
        ((ListBox) c[0]).Dispose();
}

当然还得在Form1_Load里注册事件
复制   保存
rich.MouseClick += new MouseEventHandler(rich_MouseClick);

然后设置ListBox 被选择后用被选择的关键字替换前文搜索到的字符。

下面我们来看看实现行号。


四、实现行号

这个是RichTextBox 唯一令我遗憾的地方,居然无法实现行号问题。为什么呢?我首先想到的是自己画。用rich.CreateGraphics()来画。但是,由于画的时候发生在窗体被创建时,所以画不成功,而被RichTextBox 本身的绘制给覆盖了。

然后我选择了在里面添加Label控件
复制   保存
Label l = new Label();
l.Name = "l";
l.Top = 0;
l.TextAlign = ContentAlignment.TopRight;
l.Width = 40;
l.Text = "1";
l.Font = new Font("宋体", 12, (FontStyle.Regular));
l.Height = this.Height;
l.BackColor = Color.Gray;
l.BorderStyle = BorderStyle.None;
rich.Controls.Add(l);

rich.SelectionIndent = 40;

rich.SelectionIndent = 40;是把光标对齐到左边距40的位置,防止光标被Label覆盖。

实现编号还不是太难。麻烦出在如何让Lable能跟随RichTextBox 的滚动条滚动。不说实现的 细节,我就假设,如果滚动条向上滚,那么Lable的Top属性增加,反之则减少。但是,RichTextBox 居然无法对ScollBar进行监测。

根本每办法知道滚动条滚动了多少位置,甚至都没办法知道滚动条滚动的方向。

尝试去除滚动条,然后之间添加新的滚动条
复制   保存
VScrollBar vs = new VScrollBar();
//vs.Dock = DockStyle.Right;
vs.Name = "vs";
vs.Maximum = 0;
vs.Minimum = 0;
vs.MaximumSize = new Size(0, 0);
vs.Top = 0;
vs.Left = rich.Parent.Width - 100 - 22;
vs.Height = rich.Parent.Height - 100 - 1;
vs.Value = 0;
vs.Scroll += new ScrollEventHandler(vs_Scroll);

rich.Controls.Add(vs);

但是非常难于实现同步滚动,位置很难控制。这个就是目前遇到的RichTextBox 的最大局限性了,非常遗憾,无法开发出这个功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值