ScintillaNET的应用

  出于工作需要,需要制作一个嵌入在桌面应用中的C语言编辑器,经过一系列调研,目前ScintillaNET应该是最合适的了,开源、轻便、功能丰富,但是踩得坑也很多,接下面一一说道。

  目前ScintillaNET托管在https://github.com/jacobslusser/ScintillaNET,拉下来重新编译。由于需要移植到.NET 2.0的平台上,需要修改源码中的对Linq的依赖,这里不多说,把目标框架改为.NET 2.0,编译,哪里报错改哪里。

1. 编辑器风格

参考:https://github.com/robinrodricks/ScintillaNET.Demo

2. 括号的匹配和高亮

为了方便多处调用该控件,继承Scintilla类,实现“自定义”控件,以下均以这种做法来实现功能。

重写OnUpdateUI事件,在UpdateUI中实现括号匹配功能。

 1 private int m_lastCaretPos =0;
 2 protected override void OnUpdateUI(UpdateUIEventArgs e)
 3 {
 4     base.OnUpdateUI(e);
 5     MatchAndLightBracket();
 6 }
 7 private void MatchAndLightBracket()
 8  {
 9     // Has the caret changed position?
10     int caretPos = this.CurrentPosition;
11     if (m_lastCaretPos != caretPos)
12     {
13         m_lastCaretPos = caretPos;
14         int bracePos1 = -1;
15         int bracePos2 = -1;
16 
17         // Is there a brace to the left or right?
18         if (caretPos > 0 && IsBrace(this.GetCharAt(caretPos - 1)))
19              bracePos1 = (caretPos - 1);
20         else if (IsBrace(this.GetCharAt(caretPos)))
21              bracePos1 = caretPos;
22 
23         if (bracePos1 >= 0)
24         {
25              // Find the matching brace
26              bracePos2 = this.BraceMatch(bracePos1);
27              if (bracePos2 == CodeEditor.InvalidPosition)
28              {
29                   ReleaseHighlightB();
30              }
31               else
32               {
33                    ReleaseHighlightB();
34                    HighlightBracket(bracePos1);
35                    HighlightBracket(bracePos2);
36               }
37          }
38          else
39          {
40                 ReleaseHighlightB();
41          }
42     }
43 }
44 private void HighlightBracket(int pos)
45 {
46     if (pos < 0)
47         return;
48     this.IndicatorFillRange(pos, 1);
49 }
50 private void ReleaseHighlightB()
51 {
52     this.IndicatorClearRange(0, this.TextLength);
53 }
54 private static bool IsBrace(int c)
55 {
56     switch (c)
57     {
58         case '(':
59         case ')':
60         case '[':
61         case ']':
62         case '{':
63         case '}':
64         case '<':
65         case '>':
66             return true;
67     }
68 
69     return false;
70 }
View Code

3. Ctrl+Z会一次性清空所有的修改

 1 protected override void OnBeforeInsert(BeforeModificationEventArgs e)
 2 {
 3     base.OnBeforeInsert(e);
 4     Count = this.Text.Length;
 5     this.BeginUndoAction();
 6 }
 7 protected override void OnInsert(ModificationEventArgs e)
 8 {
 9     base.OnInsert(e);
10     if (Count < this.Text.Length)
11         this.EndUndoAction(); 
12 }
View Code

4.缩进调整

 1 protected override void OnCharAdded(CharAddedEventArgs e)
 2 {
 3     base.OnCharAdded(e);
 4     AutoIndicator();
 5 }
 6 private void AutoIndicator()
 7 {
 8     int pos = this.CurrentPosition;
 9     if (pos > 3 && this.GetCharAt(pos - 1) == '\n' && this.GetCharAt(pos - 2) == '\r')
10     {
11         if (this.GetCharAt(pos - 3) == '{')
12         {
13             string[] Text = GetStringList();
14             string line = Text[this.CurrentLine - 1];
15             int start = line.IndexOf(line.TrimStart());
16             string ss = line.Substring(0, start);
17             string str = new string(' ',4);
18             this.InsertText(pos, ss+str);
19             this.SelectionStart = this.SelectionEnd = pos + ss.Length + 4;
20         }
21         else
22         {
23             string[] Text = GetStringList();
24             string line = Text[this.CurrentLine - 1];
25             int start = line.IndexOf(line.TrimStart());
26             string ss = line.Substring(0, start);
27             this.InsertText(pos, ss);
28             this.SelectionStart = this.SelectionEnd = pos + ss.Length;
29         }
30 
31     }
32 }
33 private string[] GetStringList()
34 {
35     string[] s = new string[] { "\n" };
36     return this.Text.Split(s, StringSplitOptions.None);
37 }
View Code

目前整理了这么多,有机会再继续深入理解和应用ScintillaNET。

 

posted @ 2019-02-15 14:34  EditCode  阅读(3439)  评论(0编辑  收藏  举报