出于工作需要,需要制作一个嵌入在桌面应用中的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 brace26 ?????????????bracePos2 = this.BraceMatch(bracePos1);27 ?????????????if (bracePos2 == CodeEditor.InvalidPosition)28 ?????????????{29 ??????????????????ReleaseHighlightB();30 ?????????????}31 ??????????????else32 ??????????????{33 ???????????????????ReleaseHighlightB();34 ???????????????????HighlightBracket(bracePos1);35 ???????????????????HighlightBracket(bracePos2);36 ??????????????}37 ?????????}38 ?????????else39 ?????????{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 }
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 }
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 ????????else22 ????????{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 }
目前整理了这么多,有机会再继续深入理解和应用ScintillaNET。
ScintillaNET的应用
原文地址:https://www.cnblogs.com/hawk007/p/10383528.html