出於工作需要,需要製作一個嵌入在桌面應用中的C語言編輯器,經過一系列調研,目前ScintillaNET應該是最合適的了,開源、輕便、功能豐富,但是踩得坑也很多,接下麵一一說道。 目前ScintillaNET托管在https://github.com/jacobslusser/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。