SharpDevelop浅析_3_文档编辑器、语法高亮显示
1、Demo界面及功能解释
启动后,打开文档(默认支持.cs, .js, .java, .aspx等类型文件的语法高亮显示,详见ICSharpCode.TextEditor\Resources\SyntaxModes.xml)、切换语言界面如下:
![](https://images.cnblogs.com/cnblogs_com/michael-zhang/31.jpg)
切换为中文语言环境后的界面如下:
![](https://images.cnblogs.com/cnblogs_com/michael-zhang/32.jpg)
功能说明:可以实时改变语言环境;提供对常用编程语言的编辑:支持语法高亮显示、括号匹配、设置书签;尚未提供查找/替换、代码折叠、代码提示/自动完成等功能。
2、SharpDevelop的Internationalization的使用
多语言的实现就是在显示时根据键获取相应语言环境下的键值(Dictionary<key,value>),因此在编写程序时应该引用键,而非直接书写要显示的字符。一般地,应用程序的显示包括菜单、状态栏、提示字符等,因此Demo中的主菜单在配置文件(参见Basic.addin)中使用label = "${res:Menu.File.Open}",退出应用程序的提示字符使用string s = StringParser.Parse("${res:Info.Exit}");。ICSharpCode.Core.dll支持语言环境的实时修改(修改后语言设置不需重启应用程序),因此要在应用程序订阅语言环境改变的事件,相关代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
语言环境的修改及事件响应
1
//a, 设置语言
2
//引自SharpPad项目的Dialogs\SelectCulturePanel.cs
3
public override bool ReceiveDialogMessage(DialogMessage message)
4
{
5
if (message == DialogMessage.OK) {
6
if (SelectedCulture != null) {
7
PropertyService.Set("CoreProperties.UILanguage", SelectedCulture);
8
}
9
}
10
return true;
11
}
12
//返回当前窗体用户选择的语言设置(从显示国家国旗的ListView控件)
13
string SelectedCulture {
14
get {
15
if (listView.SelectedItems.Count > 0) {
16
return listView.SelectedItems[0].SubItems[1].Text;
17
}
18
return null;
19
}
20
}
21
//b, 刷新当前应用程序
22
//引自SharpPad项目的SharpPad.cs
23
void IniFrm()
24
{
25
//
26
_menuStrip = new MenuStrip();
27
MenuService.AddItemsToMenu(_menuStrip.Items, this, "/michael/myMenus");
28
this.Controls.Add(_menuStrip);
29![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
30
PropertyService.PropertyChanged += new PropertyChangedEventHandler(PropertyService_PropertyChanged);
31
ResourceService.LanguageChanged += delegate {
32
//更新菜单项的Text显示
33
foreach (ToolStripItem item in _menuStrip.Items)
34
{
35
if (item is IStatusUpdate)
36
{
37
((IStatusUpdate)item).UpdateText();
38
}
39
}
40
};
41
}
42
//引自ICSharpCode.Core的src\AddinTree\Addin\DefaultDoozers\MenuItem\Gui\IStatusUpdate.Core
43
using System;
44
namespace ICSharpCode.Core
45
{
46
public interface IStatusUpdate
47
{
48
void UpdateStatus();
49
void UpdateText();
50
}
51
}
另外,可以看到Demo中的选项命令窗口也采用了插件模式来构造窗体(实现细节就不多谈了),容器窗体是TreeViewOption,插件窗体如:SelectCulturePanel, SelectStylePanel, DemoNothing,真是“扩展--无处不在”呀。SharpDevelop源码中的这些窗体的成员控件是通过.xfrm配置文件配置,窗体继承自XmlUserControl来根据配置文件生成控件,有一定的灵活性。
新的语言包资源文件放在\data\resources\目录下(如StringResources.cn-gb.resources),注意应用程序默认语言选项以及在未找到相关语言资源时都是引用Entry中的myRes.resx资源文件;语言声明文件是\data\resources\languages\LanguageDefinition.xml,其格式如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
LanguageDefinition.xml
1
<Languages>
2
<Languages name="Chinese (GB)" code="cn-gb" page="" icon="chinalg.png" />
3
<Languages name="German" code="de" page="" icon="germany.png" />
4
<Languages name="English" code="en" page="" icon="uk.png" />
5
</Languages>
SharpPad中动态显示可选语言项的分析类是LanguageService.cs和Language.cs,此处就不多解释了。
3、SharpDevelop的Internationalization的实现分析
SharpDevelop的多语言支持的键值对是通过本地资源文件存储的,当Demo中更改语言环境设置时,引发ICSharpCode.Core.dll中的事件及方法顺序如下:
PropertyService类的属性更新引发PropertyChanged事件 -> ResourceService响应接收到的事件并重新加载保存在内存中的资源键值对,然后引发LanguageChanged事件(由使用端接收并作相关处理,如Demo中的SharpPad.cs中的事件订阅/处理)属性更新的相关代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
属性更改
1
//PropertyService类实际是提供了对Properties类的包装,因此直接看Properties类中的代码:
2
//引自ICSharpCode.Core\src\Services\PropertService\Properties.cs
3
public void Set<T>(string property, T value)
4
{
5
T oldValue = default(T);
6
if (!properties.ContainsKey(property)) {
7
properties.Add(property, value);
8
} else {
9
oldValue = Get<T>(property, value);
10
properties[property] = value;
11
}
12
OnPropertyChanged(new PropertyChangedEventArgs(this, property, oldValue, value));
13
}
14
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
15
{
16
if (PropertyChanged != null) {
17
PropertyChanged(this, e);
18
}
19
}
20
public delegate void PropertyChangedEventHandler(object sender, PropertyChangedEventArgs e);
21
public event PropertyChangedEventHandler PropertyChanged;
资源服务类的事件响应代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
ResourceService类的事件响应
1
//引自ICSharpCode.Core\src\Services\ResourceService\ResourceService.cs
2
//首先在类的初始化中订阅属性更改事件:
3
PropertyService.PropertyChanged += new PropertyChangedEventHandler(OnPropertyChange);
4
//类级别变量:
5
static Hashtable localStrings = null;
6
static Hashtable localIcons = null;
7
public static event EventHandler LanguageChanged;
8
//事件响应:
9
static void OnPropertyChange(object sender, PropertyChangedEventArgs e)
10
{
11
if (e.Key == uiLanguageProperty && e.NewValue != e.OldValue) {
12
LoadLanguageResources((string)e.NewValue);
13
if (LanguageChanged != null)
14
LanguageChanged(null, e);
15
}
16
}
17
static void LoadLanguageResources(string language)
18
{
19
try
20
{
21
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(language);
22
}
23
catch (Exception)
24
{
25
try
26
{
27
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(language.Split('-')[0]);
28
}
29
catch (Exception) { }
30
}
31![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
32
localStrings = Load(stringResources, language);
33
if (localStrings == null && language.IndexOf('-') > 0)
34
{
35
localStrings = Load(stringResources, language.Split('-')[0]);
36
}
37![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
38
localIcons = Load(imageResources, language);
39
if (localIcons == null && language.IndexOf('-') > 0)
40
{
41
localIcons = Load(imageResources, language.Split('-')[0]);
42
}
43![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
44
localStringsResMgrs.Clear();
45
localIconsResMgrs.Clear();
46
currentLanguage = language;
47
foreach (ResourceAssembly ra in resourceAssemblies)
48
{
49
ra.Load();
50
}
51
}
52
static Hashtable Load(string name, string language)
53
{
54
return Load(resourceDirectory + Path.DirectorySeparatorChar + name + "." + language + ".resources");
55
}
56
static Hashtable Load(string fileName)
57
{
58
if (File.Exists(fileName)) {
59
Hashtable resources = new Hashtable();
60
ResourceReader rr = new ResourceReader(fileName);
61
foreach (DictionaryEntry entry in rr) {
62
resources.Add(entry.Key, entry.Value);
63
}
64
rr.Close();
65
return resources;
66
}
67
return null;
68
}
4、SharpDevelop的文档管理的基本概念
代码编写工具的核心是代码编辑窗口(如打开一个.cs文件的窗口),如何在应用程序中存储该窗口内的字符内容?有些文件可能有上千行,统计下来可能有过万个字符,如果使用string对象存储字符内容,显然是不能满足性能要求,而且要实现语法高亮显示的话,还需要区分存储TextWord和相应颜色……
先看一下字符管理的基本要求:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
ITextBufferStrategy接口
1
//引自ICSharpCode.TextEditor\src\Document\TextBufferStrategy\ITextBufferStrategy.cs
2
namespace ICSharpCode.TextEditor.Document
3
{
4
/// <summary>
5
/// Interface to describe a sequence of characters that can be edited.
6
/// </summary>
7
public interface ITextBufferStrategy
8
{
9
/// <value>
10
/// The current length of the sequence of characters that can be edited.
11
/// </value>
12
int Length {
13
get;
14
}
15
16
/// <summary>
17
/// Inserts a string of characters into the sequence.
18
/// </summary>
19
/// <param name="offset">
20
/// offset where to insert the string.
21
/// </param>
22
/// <param name="text">
23
/// text to be inserted.
24
/// </param>
25
void Insert(int offset, string text);
26
27
/// <summary>
28
/// Removes some portion of the sequence.
29
/// </summary>
30
/// <param name="offset">
31
/// offset of the remove.
32
/// </param>
33
/// <param name="length">
34
/// number of characters to remove.
35
/// </param>
36
void Remove(int offset, int length);
37
38
/// <summary>
39
/// Replace some portion of the sequence.
40
/// </summary>
41
/// <param name="offset">
42
/// offset.
43
/// </param>
44
/// <param name="length">
45
/// number of characters to replace.
46
/// </param>
47
/// <param name="text">
48
/// text to be replaced with.
49
/// </param>
50
void Replace(int offset, int length, string text);
51
52
/// <summary>
53
/// Fetches a string of characters contained in the sequence.
54
/// </summary>
55
/// <param name="offset">
56
/// Offset into the sequence to fetch
57
/// </param>
58
/// <param name="length">
59
/// number of characters to copy.
60
/// </param>
61
string GetText(int offset, int length);
62
63
/// <summary>
64
/// Returns a specific char of the sequence.
65
/// </summary>
66
/// <param name="offset">
67
/// Offset of the char to get.
68
/// </param>
69
char GetCharAt(int offset);
70
71
/// <summary>
72
/// This method sets the stored content.
73
/// </summary>
74
/// <param name="text">
75
/// The string that represents the character sequence.
76
/// </param>
77
void SetContent(string text);
78
}
79
}
SharpDevelop采用的策略是使用带Gap的字符,Gap的长度小于预定规格时,按约定增加一定长度(有些类似于SqlServer的表空间管理?),插入/修改/删除字符时只是修改Gap的长度和位置和移动部分字符,核心函数如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
GapTextBufferStrategy类
1
//引自ICSharpCode.TextEditor\src\Document\TextBufferStrategy\GapTextBufferStrategy.cs
2
//类级别变量:
3
char[] buffer = new char[0];
4
int gapBeginOffset = 0;
5
int gapEndOffset = 0;
6
/// <summary>
7
/// 小于此长度时增长Buffer/Gap
8
/// </summary>
9
int minGapLength = 32;
10
/// <summary>
11
/// 每次需要增长时,增长此长度的Gap
12
/// </summary>
13
int maxGapLength = 256;
14
//重要函数:
15
public void SetContent(string text)
16
{
17
if (text == null) {
18
text = String.Empty;
19
}
20
buffer = text.ToCharArray();
21
gapBeginOffset = gapEndOffset = 0;
22
}
23
public void Insert(int offset, string text)
24
{
25
Replace(offset, 0, text);
26
}
27
public void Remove(int offset, int length)
28
{
29
Replace(offset, length, String.Empty);
30
}
31
public void Replace(int offset, int length, string text)
32
{
33
if (text == null) {
34
text = String.Empty;
35
}
36
37
// Math.Max is used so that if we need to resize the array
38
// the new array has enough space for all old chars
39
PlaceGap(offset + length, Math.Max(text.Length - length, 0));
40
text.CopyTo(0, buffer, offset, text.Length);
41
gapBeginOffset += text.Length - length;
42
}
43
void PlaceGap(int offset, int length)
44
{
45
int deltaLength = GapLength - length;
46
// 如果Gap的长度足够大,则只是作移动相关字符的处理
47
if (minGapLength <= deltaLength && deltaLength <= maxGapLength) {
48
int delta = gapBeginOffset - offset;
49
// check if the gap is already in place
50
if (offset == gapBeginOffset) {
51
return;
52
} else if (offset < gapBeginOffset) {
53
int gapLength = gapEndOffset - gapBeginOffset;
54
Array.Copy(buffer, offset, buffer, offset + gapLength, delta);
55
} else { //offset > gapBeginOffset
56
Array.Copy(buffer, gapEndOffset, buffer, gapBeginOffset, -delta);
57
}
58
gapBeginOffset -= delta;
59
gapEndOffset -= delta;
60
return;
61
}
62
63
// 否则,需要新分析buffer的大小,并修改offset等位置数值
64
int oldLength = GapLength;
65
int newLength = maxGapLength + length;
66
int newGapEndOffset = offset + newLength;
67
char[] newBuffer = new char[buffer.Length + newLength - oldLength]; //新分配后将有maxGapLength长度的Gap
68
69
if (oldLength == 0) {
70
Array.Copy(buffer, 0, newBuffer, 0, offset);
71
Array.Copy(buffer, offset, newBuffer, newGapEndOffset, newBuffer.Length - newGapEndOffset);
72
} else if (offset < gapBeginOffset) {
73
int delta = gapBeginOffset - offset;
74
Array.Copy(buffer, 0, newBuffer, 0, offset);
75
Array.Copy(buffer, offset, newBuffer, newGapEndOffset, delta);
76
Array.Copy(buffer, gapEndOffset, newBuffer, newGapEndOffset + delta, buffer.Length - gapEndOffset);
77
} else {
78
int delta = offset - gapBeginOffset;
79
Array.Copy(buffer, 0, newBuffer, 0, gapBeginOffset);
80
Array.Copy(buffer, gapEndOffset, newBuffer, gapBeginOffset, delta);
81
Array.Copy(buffer, gapEndOffset + delta, newBuffer, newGapEndOffset, newBuffer.Length - newGapEndOffset);
82
}
83
84
buffer = newBuffer;
85
gapBeginOffset = offset;
86
gapEndOffset = newGapEndOffset;
87
}
有了基本的数据容器,核心问题已经解决了,但是在绘制界面时直接使用上面的类,显然不够方便,于是就定义了LineSegment和TextWord类来分别存储行、单词,注意这两个类存储的只是int类型的offset和length信息,而不存储字符或字符串对象。注意TextWord类中有个HighlightColor类型的变量用以存储语法高亮显示信息。
有了上面的这些类,便可以组合起来补充些其它信息对外提供服务了,IDocument接口存在的目的即在于此,它封装了ITextEditorProperties(是否显示空格/Tab/Eol/HRuler等)、UndoStack、ITextBufferStrategy、IHighlightingStrategy、FoldingManager、BookmarkManager等属性对象。
5、SharpDevelop的SyntaxHighlighting配置文件的定义
是时候对语法高亮显示作一些分析了,此处不详述其实现,而重点分析其配置定义,从中亦可以猜出部分实现。
相关配置文件均保存在ICSharpCode.TextEditor项目\Resource\目录下
首先SyntaxMode.xml文件中显示了已定义的文件类型及其声明文件位置,其解析类参见\src\Document\HighlightingStrategy\SyntaxModes\FileSyntaxModeProvider.cs
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
SyntaxMode.xml
1
<SyntaxModes version="1.0">
2
<Mode file = "ASPX.xshd"
3
name = "ASP/XHTML"
4
extensions = ".asp;.aspx;.asax;.asmx"/>
5
6
<Mode file = "BAT-Mode.xshd"
7
name = "BAT"
8
extensions = ".bat"/>
9
10
<Mode file = "CPP-Mode.xshd"
11
name = "C++.NET"
12
extensions = ".c;.h;.cc;.C;.cpp;.hpp"/>
13
14
<Mode file = "CSharp-Mode.xshd"
15
name = "C#"
16
extensions = ".cs"/>
17
18
<Mode file = "XML-Mode.xshd"
19
name = "XML"
20
extensions = ".xml;.xsl;.xslt;.xsd;.manifest;.config;.addin;.xshd;.wxs;.proj;.csproj;.vbproj;.ilproj;.booproj;.build;.xfrm;.targets;.xaml;.xpt;.xft;.map;.wsdl;.disco"/>
21
</SyntaxModes>
取CSharp-Mode.xshd(注:xshd是Xml Syntax Highlighting Definition的缩写)为例,查看其定义:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
CSharp-Mode.xshd
1
<?xml version="1.0"?>
2
<SyntaxDefinition name = "C#" extensions = ".cs">
3
<Properties>
4
<Property name="LineComment" value="//"/>
5
</Properties>
6
<Digits name = "Digits" bold = "false" italic = "false" color = "DarkBlue"/>
7
<RuleSets>
8
<RuleSet ignorecase="false">
9
<Delimiters>&<>~!%^*()-+=|\#/{}[]:;"' , .?</Delimiters>
10
<Span name = "PreprocessorDirectives" rule = "PreprocessorSet" bold="false" italic="false" color="Green" stopateol = "true">
11
<Begin>#</Begin>
12
</Span>
13
<Span name = "BlockComment" rule = "CommentMarkerSet" bold = "false" italic = "false" color = "Green" stopateol = "false">
14
<Begin>/*</Begin>
15
<End>*/</End>
16
</Span>
17
<KeyWords name = "Punctuation" bold = "false" italic = "false" color = "DarkGreen">
18
<Key word = "?" />
19
<Key word = "," />
20
<Key word = "." />
21
<Key word = ";" />
22
<Key word = "(" />
23
<Key word = ")" />
24
<Key word = "[" />
25
<Key word = "]" />
26
<Key word = "{" />
27
<Key word = "}" />
28
<Key word = "+" />
29
<Key word = "-" />
30
<Key word = "/" />
31
<Key word = "%" />
32
<Key word = "*" />
33
<Key word = "<" />
34
<Key word = ">" />
35
<Key word = "^" />
36
<Key word = "=" />
37
<Key word = "~" />
38
<Key word = "!" />
39
<Key word = "|" />
40
<Key word = "&" />
41
</KeyWords>
42
43
<KeyWords name = "AccessKeywords" bold="true" italic="false" color="Black">
44
<Key word = "this" />
45
<Key word = "base" />
46
</KeyWords>
47
48
<KeyWords name = "OperatorKeywords" bold="true" italic="false" color="DarkCyan">
49
<Key word = "as" />
50
<Key word = "is" />
51
<Key word = "new" />
52
<Key word = "sizeof" />
53
<Key word = "typeof" />
54
<Key word = "true" />
55
<Key word = "false" />
56
<Key word = "stackalloc" />
57
</KeyWords>
58
</RuleSet>
59
</RuleSets>
60
</SyntaxDefinition>
上面的文件公摘选了部分标签,其中
<Property>标签定义了指定名称属性的指定值
<Digits>标签定义了数值的字体显示样式
<Delimiters>定义了分隔单词的字符
<Span>定义了包含在此指定Begin/End中的字符的显示样式,注意没有<End>标签的一般设stopateol(stop at end-of-line)为true
<KeyWords>指定了其子集<Key>声明的单词的显示样式
6、SharpDevelop的TextEditor控件的实现概述
接下来的任务是要显示和支持用户输入了,直接使用TextBox或RichTextBox好像都不太现实,效率上也必定有不少损失,于是SharpDevelop的方式是直接继承自Control, Panel, UserControl 的方式来实现编辑控件(参见ICSharpCode.TextEditor项目\src\Gui\...)。
首先使用TextEditorControlBase(继承自UserControl)封装当前文件路径、Encoding、IDocument对象、ITextEditorProperties对象、快捷键列表(Dictionary<Keys, IEditAction>类型)的变量,提供LoadFile()、SaveFile()等重要方法。
TextEditorControl类继承自上面的类,并声明了Panel、Splitter、TextAreaControl、PrintDocument控件,其中显示文件的核心控件是TextAreaControl,该控件在此类中被声明了两个变量,默认只有一个primaryTextArea显示,支持切分为两个窗口的显示,当有两个窗口时,Splitter控件才有效;PrinDocument控件用以打印输出内容;该类的另一个重要功能是提供了UnDo()、Redo()方法。
TextAreaControl(继承自Panel)控件,封装了TextArea、VScrollBar、HScrollBar控件,其中TextArea负责文件数据显示,另外两个控件负责文件内容大于可见尺寸时的滚动条服务。
TextArea(继承自Control)封装了TextView, IconBarMargin, GutterMargin, FoldMargin, SelectionManager, Caret 等控件或类对象,其中前四个控件均继承自AbstractMargin,代表区域对象,各自负责字符区域(较大的文件内容绘制区)、图标区域(如Bookmark图标所在列)、Gutter区域(如行号)、折叠控制区域的绘制,SelectionManager用以控制选中项,Caret用以控制光标位置调整和显示。
下面是一些我在读代码的过程中有过的疑问及解答:
a, 加载文件时发生了什么?
答:加载文件时控件根据文件的后缀名选择了相应的高亮显示策略,然后读取文件的内容并生成相应的GapTextBufferStrategy, LineSegment, TextWord 等对象,并且对所有的TextWord对象的HighlightColor类型成员变量完成分析赋值(用以在Paint函数中显示),相关代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
LoadFile()相关代码
1
//取自TextEditorControlBase.cs
2
public void LoadFile(string fileName, bool autoLoadHighlighting, bool autodetectEncoding)
3
{
4
BeginUpdate();
5
document.TextContent = String.Empty;
6
document.UndoStack.ClearAll();
7
document.BookmarkManager.Clear();
8
if (autoLoadHighlighting) {
9
//根据文件扩展名判断并赋值高亮显示的策略
10
document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategyForFile(fileName);
11
}
12
13
if (autodetectEncoding) {
14
Encoding encoding = this.Encoding;
15
//赋值
16
Document.TextContent = Util.FileReader.ReadFileContent(fileName, ref encoding, this.TextEditorProperties.Encoding);
17
this.Encoding = encoding;
18
} else {
19
using (StreamReader reader = new StreamReader(fileName, this.Encoding)) {
20
Document.TextContent = reader.ReadToEnd();
21
}
22
}
23
24
this.FileName = fileName;
25
OptionsChanged();
26
Document.UpdateQueue.Clear();
27
EndUpdate();
28
29
Refresh();
30
}
31
//引自DefaultDocument.cs
32
ITextBufferStrategy textBufferStrategy = null;
33
ILineManager lineTrackingStrategy = null;
34
public string TextContent {
35
get {
36
return GetText(0, textBufferStrategy.Length);
37
}
38
set {
39
Debug.Assert(textBufferStrategy != null);
40
Debug.Assert(lineTrackingStrategy != null);
41
OnDocumentAboutToBeChanged(new DocumentEventArgs(this, 0, 0, value));
42
//赋值
43
textBufferStrategy.SetContent(value);
44
//赋值 && 分析并完成高亮分析的赋值
45
lineTrackingStrategy.SetContent(value);
46
47
OnDocumentChanged(new DocumentEventArgs(this, 0, 0, value));
48
OnTextContentChanged(EventArgs.Empty);
49
}
50
}
51
//引自DefaultLineManager.cs
52
public void SetContent(string text)
53
{
54
lineCollection.Clear();
55
if (text != null) {
56
textLength = text.Length;
57
// 生成LineSegment集合
58
CreateLines(text, 0, 0);
59
// 高亮分析
60
RunHighlighter();
61
}
62
}
b, 控件如何响应键盘事件?
答:对于方向键及快捷功能键通过预定义的实现IEditAction接口的类响应(执行功能,不影响字符内容);其它字母/数字键直接输入,同时执行更新Folding, Bookmark, Higlighting等属性信息。相关代码:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
键盘事件响应
1
//功能键的定义(引自TextEditorControlBase.cs):
2
protected Dictionary<Keys, IEditAction> editactions = new Dictionary<Keys, IEditAction>();
3
protected TextEditorControlBase()
4
{
5
GenerateDefaultActions();
6
HighlightingManager.Manager.ReloadSyntaxHighlighting += new EventHandler(ReloadHighlighting);
7
}
8
void GenerateDefaultActions()
9
{
10
editactions[Keys.Left] = new CaretLeft();
11
editactions[Keys.Left | Keys.Shift] = new ShiftCaretLeft();
12
editactions[Keys.Left | Keys.Control] = new WordLeft();
13
editactions[Keys.Left | Keys.Control | Keys.Shift] = new ShiftWordLeft();
14
editactions[Keys.Right] = new CaretRight();
15
editactions[Keys.Right | Keys.Shift] = new ShiftCaretRight();
16
editactions[Keys.Right | Keys.Control] = new WordRight();
17
editactions[Keys.Right | Keys.Control | Keys.Shift] = new ShiftWordRight();
18
editactions[Keys.Up] = new CaretUp();
19
editactions[Keys.Up | Keys.Shift] = new ShiftCaretUp();
20
editactions[Keys.Up | Keys.Control] = new ScrollLineUp();
21
editactions[Keys.Down] = new CaretDown();
22
editactions[Keys.Down | Keys.Shift] = new ShiftCaretDown();
23
editactions[Keys.Down | Keys.Control] = new ScrollLineDown();
24
25
editactions[Keys.Insert] = new ToggleEditMode();
26
editactions[Keys.Insert | Keys.Control] = new Copy();
27
editactions[Keys.Insert | Keys.Shift] = new Paste();
28
editactions[Keys.Delete] = new Delete();
29
editactions[Keys.Delete | Keys.Shift] = new Cut();
30
editactions[Keys.Home] = new Home();
31
editactions[Keys.Home | Keys.Shift] = new ShiftHome();
32
editactions[Keys.Home | Keys.Control] = new MoveToStart();
33
editactions[Keys.Home | Keys.Control | Keys.Shift] = new ShiftMoveToStart();
34
editactions[Keys.End] = new End();
35
editactions[Keys.End | Keys.Shift] = new ShiftEnd();
36
editactions[Keys.End | Keys.Control] = new MoveToEnd();
37
editactions[Keys.End | Keys.Control | Keys.Shift] = new ShiftMoveToEnd();
38
editactions[Keys.PageUp] = new MovePageUp();
39
editactions[Keys.PageUp | Keys.Shift] = new ShiftMovePageUp();
40
editactions[Keys.PageDown] = new MovePageDown();
41
editactions[Keys.PageDown | Keys.Shift] = new ShiftMovePageDown();
42
43
editactions[Keys.Return] = new Return();
44
editactions[Keys.Tab] = new Tab();
45
editactions[Keys.Tab | Keys.Shift] = new ShiftTab();
46
editactions[Keys.Back] = new Backspace();
47
editactions[Keys.Back | Keys.Shift] = new Backspace();
48
49
editactions[Keys.X | Keys.Control] = new Cut();
50
editactions[Keys.C | Keys.Control] = new Copy();
51
editactions[Keys.V | Keys.Control] = new Paste();
52
53
editactions[Keys.A | Keys.Control] = new SelectWholeDocument();
54
editactions[Keys.Escape] = new ClearAllSelections();
55
56
editactions[Keys.Divide | Keys.Control] = new ToggleComment();
57
editactions[Keys.OemQuestion | Keys.Control] = new ToggleComment();
58
59
editactions[Keys.Back | Keys.Alt] = new Actions.Undo();
60
editactions[Keys.Z | Keys.Control] = new Actions.Undo();
61
editactions[Keys.Y | Keys.Control] = new Redo();
62
63
editactions[Keys.Delete | Keys.Control] = new DeleteWord();
64
editactions[Keys.Back | Keys.Control] = new WordBackspace();
65
editactions[Keys.D | Keys.Control] = new DeleteLine();
66
editactions[Keys.D | Keys.Shift | Keys.Control] = new DeleteToLineEnd();
67
68
editactions[Keys.B | Keys.Control] = new GotoMatchingBrace();
69
}
70
internal IEditAction GetEditAction(Keys keyData)
71
{
72
if (!editactions.ContainsKey(keyData)) {
73
return null;
74
}
75
return (IEditAction)editactions[keyData];
76
}
77
//功能键的响应(取自TextArea.cs):
78
protected override bool ProcessDialogKey(Keys keyData)
79
{
80
return ExecuteDialogKey(keyData) || base.ProcessDialogKey(keyData);
81
}
82
public bool ExecuteDialogKey(Keys keyData)
83
{
84
// try, if a dialog key processor was set to use this
85
if (DoProcessDialogKey != null && DoProcessDialogKey(keyData)) {
86
return true;
87
}
88
89
if (keyData == Keys.Back || keyData == Keys.Delete || keyData == Keys.Enter) {
90
if (TextEditorProperties.UseCustomLine == true) {
91
if (SelectionManager.HasSomethingSelected) {
92
if (Document.CustomLineManager.IsReadOnly(SelectionManager.SelectionCollection[0], false))
93
return true;
94
} else {
95
int curLineNr = Document.GetLineNumberForOffset(Caret.Offset);
96
if (Document.CustomLineManager.IsReadOnly(curLineNr, false) == true)
97
return true;
98
if ((Caret.Column == 0) && (curLineNr - 1 >= 0) && keyData == Keys.Back &&
99
Document.CustomLineManager.IsReadOnly(curLineNr - 1, false) == true)
100
return true;
101
if (keyData == Keys.Delete) {
102
LineSegment curLine = Document.GetLineSegment(curLineNr);
103
if (curLine.Offset + curLine.Length == Caret.Offset &&
104
Document.CustomLineManager.IsReadOnly(curLineNr + 1, false) == true) {
105
return true;
106
}
107
}
108
}
109
}
110
}
111
112
// if not (or the process was 'silent', use the standard edit actions
113
IEditAction action = motherTextEditorControl.GetEditAction(keyData);
114
AutoClearSelection = true;
115
if (action != null) {
116
motherTextEditorControl.BeginUpdate();
117
try {
118
lock (Document) {
119
// 执行相关的功能操作
120
action.Execute(this);
121
if (SelectionManager.HasSomethingSelected && AutoClearSelection /*&& caretchanged*/) {
122
if (Document.TextEditorProperties.DocumentSelectionMode == DocumentSelectionMode.Normal) {
123
SelectionManager.ClearSelection();
124
}
125
}
126
}
127
} finally {
128
motherTextEditorControl.EndUpdate();
129
Caret.UpdateCaretPosition();
130
}
131
return true;
132
}
133
return false;
134
}
135![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
136
//输入键的响应(取自TextArea.cs):
137
protected override void OnKeyPress(KeyPressEventArgs e)
138
{
139
base.OnKeyPress(e);
140
SimulateKeyPress(e.KeyChar);
141
e.Handled = true;
142
}
143
public void SimulateKeyPress(char ch)
144
{
145
if (Document.ReadOnly) {
146
return;
147
}
148
149
if (TextEditorProperties.UseCustomLine == true) {
150
if (SelectionManager.HasSomethingSelected) {
151
if (Document.CustomLineManager.IsReadOnly(SelectionManager.SelectionCollection[0], false))
152
return;
153
} else if (Document.CustomLineManager.IsReadOnly(Caret.Line, false) == true)
154
return;
155
}
156
157
if (ch < ' ') {
158
return;
159
}
160
161
if (!HiddenMouseCursor && TextEditorProperties.HideMouseCursor) {
162
HiddenMouseCursor = true;
163
Cursor.Hide();
164
}
165
CloseToolTip();
166
167
motherTextEditorControl.BeginUpdate();
168
// INSERT char
169
if (!HandleKeyPress(ch)) {
170
switch (Caret.CaretMode) {
171
case CaretMode.InsertMode:
172
InsertChar(ch);
173
break;
174
case CaretMode.OverwriteMode:
175
ReplaceChar(ch);
176
break;
177
default:
178
Debug.Assert(false, "Unknown caret mode " + Caret.CaretMode);
179
break;
180
}
181
}
182
183
int currentLineNr = Caret.Line;
184
int delta = Document.FormattingStrategy.FormatLine(this, currentLineNr, Document.PositionToOffset(Caret.Position), ch);
185
186
motherTextEditorControl.EndUpdate();
187
if (delta != 0) {
188
// this.motherTextEditorControl.UpdateLines(currentLineNr, currentLineNr);
189
}
190
}
191
//输入键通过底层的方法输入字符和更改高亮显示,如下分析(以Insert为例,取自DefaultDocument.cs):
192
public void Insert(int offset, string text)
193
{
194
if (readOnly) {
195
return;
196
}
197
OnDocumentAboutToBeChanged(new DocumentEventArgs(this, offset, -1, text));
198
DateTime time = DateTime.Now;
199
//增加字符
200
textBufferStrategy.Insert(offset, text);
201
202
time = DateTime.Now;
203
//更新LineSegment, TextWord对象
204
lineTrackingStrategy.Insert(offset, text);
205
206
time = DateTime.Now;
207
208
undoStack.Push(new UndoableInsert(this, offset, text));
209
210
time = DateTime.Now;
211
OnDocumentChanged(new DocumentEventArgs(this, offset, -1, text));
212
}
213
// 追踪到DefaultLineManager.cs中Insert()方法实际上调用到Replace(offset,length,string.Empty)方法:
214
public void Replace(int offset, int length, string text)
215
{
216
int lineNumber = GetLineNumberForOffset(offset);
217
int insertLineNumber = lineNumber;
218
if (Remove(lineNumber, offset, length)) {
219
--lineNumber;
220
}
221
222
lineNumber += Insert(insertLineNumber, offset, text);
223
224
int delta = -length;
225
if (text != null) {
226
delta = text.Length + delta;
227
}
228
229
if (delta != 0) {
230
AdaptLineOffsets(lineNumber, delta);
231
}
232
//启用高亮显示分析 ----- 注:此时的 markLines 仅存储变化的相关行,而SetContent时存储的是所有行,因此只是按需分析
233
RunHighlighter();
234
}
c, 文件字符的绘制究竟是在何处?
答:在TextView.cs中的public override void Paint(Graphics g, Rectangle rect)函数中,重要函数:PaintLinePart(),辅助绘制函数:DrawDocumentWord(), DrawBracketHighlight(), DrawSpaceMarker(), DrawVerticalRuler() 等
d, 括号匹配在何处被定义和捕捉更新?
答:TextArea.cs中的List<BracketHighlightingSheme> bracketshemes = new List<BracketHighlightingSheme>();变量存储在查找的匹配项,SearchMatchingBracket()方法中搜索并更新匹配项的显示,相关代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
括号匹配
1
//引自TextArea.cs
2
List<BracketHighlightingSheme> bracketshemes = new List<BracketHighlightingSheme>();
3
Caret caret;
4
public TextArea(TextEditorControl motherTextEditorControl, TextAreaControl motherTextAreaControl)
5
{
6
// 省略无关代码
7
bracketshemes.Add(new BracketHighlightingSheme('{', '}'));
8
bracketshemes.Add(new BracketHighlightingSheme('(', ')'));
9
bracketshemes.Add(new BracketHighlightingSheme('[', ']'));
10
11
caret.PositionChanged += new EventHandler(SearchMatchingBracket);
12
// 省略无关代码
13
}
14
void SearchMatchingBracket(object sender, EventArgs e)
15
{
16
if (!TextEditorProperties.ShowMatchingBracket) {
17
textView.Highlight = null;
18
return;
19
}
20
bool changed = false;
21
if (caret.Offset == 0) {
22
if (textView.Highlight != null) {
23
int line = textView.Highlight.OpenBrace.Y;
24
int line2 = textView.Highlight.CloseBrace.Y;
25
textView.Highlight = null;
26
UpdateLine(line);
27
UpdateLine(line2);
28
}
29
return;
30
}
31
foreach (BracketHighlightingSheme bracketsheme in bracketshemes) {
32
// if (bracketsheme.IsInside(textareapainter.Document, textareapainter.Document.Caret.Offset)) {
33
Highlight highlight = bracketsheme.GetHighlight(Document, Caret.Offset - 1);
34
if (textView.Highlight != null && textView.Highlight.OpenBrace.Y >=0 && textView.Highlight.OpenBrace.Y < Document.TotalNumberOfLines) {
35
//取消旧匹配项的高亮显示
36
UpdateLine(textView.Highlight.OpenBrace.Y);
37
}
38
if (textView.Highlight != null && textView.Highlight.CloseBrace.Y >=0 && textView.Highlight.CloseBrace.Y < Document.TotalNumberOfLines) {
39
//取消旧匹配项的高亮显示
40
UpdateLine(textView.Highlight.CloseBrace.Y);
41
}
42
textView.Highlight = highlight;
43
if (highlight != null) {
44
changed = true;
45
break;
46
}
47
// }
48
}
49
if (changed || textView.Highlight != null) {
50
int line = textView.Highlight.OpenBrace.Y;
51
int line2 = textView.Highlight.CloseBrace.Y;
52
if (!changed) {
53
textView.Highlight = null;
54
}
55
//更新显示新匹配项 OpenBrace
56
UpdateLine(line);
57
//更新显示新匹配项 CloseBrace
58
UpdateLine(line2);
59
}
60
}
7、待分析的部分
本篇讨论暂未涉及如下(有价值?)内容的分析:
SyntaxHighlighting实现分析
BookmarkManager, FoldingManager, FormattingManager等
Paint()处理中坐标分析及转换
启动后,打开文档(默认支持.cs, .js, .java, .aspx等类型文件的语法高亮显示,详见ICSharpCode.TextEditor\Resources\SyntaxModes.xml)、切换语言界面如下:
![](https://images.cnblogs.com/cnblogs_com/michael-zhang/31.jpg)
切换为中文语言环境后的界面如下:
![](https://images.cnblogs.com/cnblogs_com/michael-zhang/32.jpg)
功能说明:可以实时改变语言环境;提供对常用编程语言的编辑:支持语法高亮显示、括号匹配、设置书签;尚未提供查找/替换、代码折叠、代码提示/自动完成等功能。
2、SharpDevelop的Internationalization的使用
多语言的实现就是在显示时根据键获取相应语言环境下的键值(Dictionary<key,value>),因此在编写程序时应该引用键,而非直接书写要显示的字符。一般地,应用程序的显示包括菜单、状态栏、提示字符等,因此Demo中的主菜单在配置文件(参见Basic.addin)中使用label = "${res:Menu.File.Open}",退出应用程序的提示字符使用string s = StringParser.Parse("${res:Info.Exit}");。ICSharpCode.Core.dll支持语言环境的实时修改(修改后语言设置不需重启应用程序),因此要在应用程序订阅语言环境改变的事件,相关代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
5
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
6
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
7
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
9
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
10
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
12
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
13
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
14
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
15
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
16
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
17
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
18
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
19
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
20
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
21
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
22
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
23
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
24
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
25
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
26
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
27
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
28
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
29
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
30
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
31
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
32
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
33
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
34
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
35
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
36
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
37
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
38
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
39
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
40
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
41
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
42
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
43
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
44
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
45
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
46
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
47
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
48
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
49
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
50
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
51
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
另外,可以看到Demo中的选项命令窗口也采用了插件模式来构造窗体(实现细节就不多谈了),容器窗体是TreeViewOption,插件窗体如:SelectCulturePanel, SelectStylePanel, DemoNothing,真是“扩展--无处不在”呀。SharpDevelop源码中的这些窗体的成员控件是通过.xfrm配置文件配置,窗体继承自XmlUserControl来根据配置文件生成控件,有一定的灵活性。
新的语言包资源文件放在\data\resources\目录下(如StringResources.cn-gb.resources),注意应用程序默认语言选项以及在未找到相关语言资源时都是引用Entry中的myRes.resx资源文件;语言声明文件是\data\resources\languages\LanguageDefinition.xml,其格式如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
5
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
SharpPad中动态显示可选语言项的分析类是LanguageService.cs和Language.cs,此处就不多解释了。
3、SharpDevelop的Internationalization的实现分析
SharpDevelop的多语言支持的键值对是通过本地资源文件存储的,当Demo中更改语言环境设置时,引发ICSharpCode.Core.dll中的事件及方法顺序如下:
PropertyService类的属性更新引发PropertyChanged事件 -> ResourceService响应接收到的事件并重新加载保存在内存中的资源键值对,然后引发LanguageChanged事件(由使用端接收并作相关处理,如Demo中的SharpPad.cs中的事件订阅/处理)属性更新的相关代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
5
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
6
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
7
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
9
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
12
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
13
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
14
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
15
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
16
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
17
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
19
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
20
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
21
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
资源服务类的事件响应代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
5
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
6
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
7
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
8
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
9
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
10
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
11
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
12
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
13
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
14
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
15
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
16
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
17
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
18
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
19
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
20
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
21
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
22
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
23
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
24
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
25
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
26
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
27
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
28
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
29
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
30
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
31
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
32
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
33
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
34
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
35
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
36
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
37
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
38
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
39
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
40
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
41
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
42
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
43
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
44
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
45
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
46
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
47
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
48
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
49
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
50
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
51
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
52
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
53
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
54
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
55
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
56
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
57
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
58
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
59
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
60
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
61
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
62
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
63
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
64
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
65
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
66
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
67
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
68
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
4、SharpDevelop的文档管理的基本概念
代码编写工具的核心是代码编辑窗口(如打开一个.cs文件的窗口),如何在应用程序中存储该窗口内的字符内容?有些文件可能有上千行,统计下来可能有过万个字符,如果使用string对象存储字符内容,显然是不能满足性能要求,而且要实现语法高亮显示的话,还需要区分存储TextWord和相应颜色……
先看一下字符管理的基本要求:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
4
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
5
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
6
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
7
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
9
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
10
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
12
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
13
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
14
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
15
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
16
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
17
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
19
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
20
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
21
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
22
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
23
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
24
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
25
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
26
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
27
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
28
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
29
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
30
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
31
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
32
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
33
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
34
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
35
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
36
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
37
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
38
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
39
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
40
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
41
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
42
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
43
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
44
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
45
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
46
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
47
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
48
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
49
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
50
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
51
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
52
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
53
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
54
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
55
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
56
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
57
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
58
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
59
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
60
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
61
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
62
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
63
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
64
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
65
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
66
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
67
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
68
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
69
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
70
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
71
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
72
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
73
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
74
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
75
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
76
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
77
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
78
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
79
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
SharpDevelop采用的策略是使用带Gap的字符,Gap的长度小于预定规格时,按约定增加一定长度(有些类似于SqlServer的表空间管理?),插入/修改/删除字符时只是修改Gap的长度和位置和移动部分字符,核心函数如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
5
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
6
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
7
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
9
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
10
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
11
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
12
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
13
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
14
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
15
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
16
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
17
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
18
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
19
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
20
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
21
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
22
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
23
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
24
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
25
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
26
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
27
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
28
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
29
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
30
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
31
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
32
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
33
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
34
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
35
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
36
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
37
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
38
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
39
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
40
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
41
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
42
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
43
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
44
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
45
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
46
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
47
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
48
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
49
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
50
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
51
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
52
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
53
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
54
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
55
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
56
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
57
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
58
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
59
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
60
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
61
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
62
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
63
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
64
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
65
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
66
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
67
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
68
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
69
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
70
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
71
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
72
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
73
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
74
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
75
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
76
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
77
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
78
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
79
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
80
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
81
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
82
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
83
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
84
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
85
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
86
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
87
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
有了基本的数据容器,核心问题已经解决了,但是在绘制界面时直接使用上面的类,显然不够方便,于是就定义了LineSegment和TextWord类来分别存储行、单词,注意这两个类存储的只是int类型的offset和length信息,而不存储字符或字符串对象。注意TextWord类中有个HighlightColor类型的变量用以存储语法高亮显示信息。
有了上面的这些类,便可以组合起来补充些其它信息对外提供服务了,IDocument接口存在的目的即在于此,它封装了ITextEditorProperties(是否显示空格/Tab/Eol/HRuler等)、UndoStack、ITextBufferStrategy、IHighlightingStrategy、FoldingManager、BookmarkManager等属性对象。
5、SharpDevelop的SyntaxHighlighting配置文件的定义
是时候对语法高亮显示作一些分析了,此处不详述其实现,而重点分析其配置定义,从中亦可以猜出部分实现。
相关配置文件均保存在ICSharpCode.TextEditor项目\Resource\目录下
首先SyntaxMode.xml文件中显示了已定义的文件类型及其声明文件位置,其解析类参见\src\Document\HighlightingStrategy\SyntaxModes\FileSyntaxModeProvider.cs
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
5
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
6
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
7
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
8
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
9
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
10
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
11
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
12
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
13
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
14
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
15
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
16
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
17
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
18
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
19
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
20
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
21
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
取CSharp-Mode.xshd(注:xshd是Xml Syntax Highlighting Definition的缩写)为例,查看其定义:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
5
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
6
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
7
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
8
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
9
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
10
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
11
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
12
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
13
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
14
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
15
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
16
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
17
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
18
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
19
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
20
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
21
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
22
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
23
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
24
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
25
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
26
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
27
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
28
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
29
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
30
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
31
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
32
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
33
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
34
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
35
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
36
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
37
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
38
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
39
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
40
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
41
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
42
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
43
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
44
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
45
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
46
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
47
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
48
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
49
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
50
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
51
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
52
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
53
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
54
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
55
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
56
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
57
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
58
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
59
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
60
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
上面的文件公摘选了部分标签,其中
<Property>标签定义了指定名称属性的指定值
<Digits>标签定义了数值的字体显示样式
<Delimiters>定义了分隔单词的字符
<Span>定义了包含在此指定Begin/End中的字符的显示样式,注意没有<End>标签的一般设stopateol(stop at end-of-line)为true
<KeyWords>指定了其子集<Key>声明的单词的显示样式
6、SharpDevelop的TextEditor控件的实现概述
接下来的任务是要显示和支持用户输入了,直接使用TextBox或RichTextBox好像都不太现实,效率上也必定有不少损失,于是SharpDevelop的方式是直接继承自Control, Panel, UserControl 的方式来实现编辑控件(参见ICSharpCode.TextEditor项目\src\Gui\...)。
首先使用TextEditorControlBase(继承自UserControl)封装当前文件路径、Encoding、IDocument对象、ITextEditorProperties对象、快捷键列表(Dictionary<Keys, IEditAction>类型)的变量,提供LoadFile()、SaveFile()等重要方法。
TextEditorControl类继承自上面的类,并声明了Panel、Splitter、TextAreaControl、PrintDocument控件,其中显示文件的核心控件是TextAreaControl,该控件在此类中被声明了两个变量,默认只有一个primaryTextArea显示,支持切分为两个窗口的显示,当有两个窗口时,Splitter控件才有效;PrinDocument控件用以打印输出内容;该类的另一个重要功能是提供了UnDo()、Redo()方法。
TextAreaControl(继承自Panel)控件,封装了TextArea、VScrollBar、HScrollBar控件,其中TextArea负责文件数据显示,另外两个控件负责文件内容大于可见尺寸时的滚动条服务。
TextArea(继承自Control)封装了TextView, IconBarMargin, GutterMargin, FoldMargin, SelectionManager, Caret 等控件或类对象,其中前四个控件均继承自AbstractMargin,代表区域对象,各自负责字符区域(较大的文件内容绘制区)、图标区域(如Bookmark图标所在列)、Gutter区域(如行号)、折叠控制区域的绘制,SelectionManager用以控制选中项,Caret用以控制光标位置调整和显示。
下面是一些我在读代码的过程中有过的疑问及解答:
a, 加载文件时发生了什么?
答:加载文件时控件根据文件的后缀名选择了相应的高亮显示策略,然后读取文件的内容并生成相应的GapTextBufferStrategy, LineSegment, TextWord 等对象,并且对所有的TextWord对象的HighlightColor类型成员变量完成分析赋值(用以在Paint函数中显示),相关代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
4
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
5
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
6
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
9
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
12
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
13
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
14
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
15
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
16
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
17
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
19
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
20
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
21
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
22
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
23
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
24
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
25
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
26
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
27
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
28
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
29
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
30
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
31
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
32
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
33
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
34
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
35
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
36
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
37
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
38
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
39
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
40
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
41
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
42
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
43
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
44
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
45
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
46
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
47
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
48
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
49
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
50
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
51
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
52
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
53
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
54
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
55
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
56
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
57
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
58
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
59
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
60
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
61
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
62
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
b, 控件如何响应键盘事件?
答:对于方向键及快捷功能键通过预定义的实现IEditAction接口的类响应(执行功能,不影响字符内容);其它字母/数字键直接输入,同时执行更新Folding, Bookmark, Higlighting等属性信息。相关代码:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
5
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
6
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
8
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
9
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
10
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
12
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
13
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
14
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
15
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
16
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
17
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
19
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
20
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
21
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
22
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
23
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
24
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
25
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
26
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
27
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
28
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
29
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
30
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
31
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
32
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
33
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
34
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
35
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
36
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
37
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
38
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
39
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
40
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
41
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
42
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
43
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
44
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
45
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
46
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
47
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
48
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
49
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
50
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
51
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
52
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
53
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
54
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
55
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
56
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
57
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
58
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
59
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
60
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
61
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
62
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
63
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
64
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
65
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
66
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
67
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
68
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
69
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
70
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
71
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
72
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
73
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
74
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
75
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
76
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
77
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
78
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
79
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
80
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
81
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
82
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
83
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
84
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
85
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
86
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
87
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
88
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
89
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
90
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
91
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
92
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
93
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
94
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
95
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
96
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
97
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
98
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
99
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
100
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
101
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
102
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
103
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
104
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
105
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
106
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
107
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
108
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
109
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
110
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
111
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
112
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
113
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
114
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
115
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
116
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
117
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
118
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
119
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
120
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
121
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
122
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
123
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
124
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
125
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
126
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
127
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
128
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
129
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
130
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
131
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
132
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
133
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
134
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
135
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
136
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
137
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
138
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
139
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
140
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
141
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
142
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
143
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
144
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
145
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
146
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
147
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
148
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
149
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
150
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
151
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
152
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
153
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
154
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
155
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
156
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
157
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
158
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
159
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
160
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
161
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
162
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
163
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
164
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
165
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
166
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
167
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
168
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
169
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
170
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
171
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
172
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
173
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
174
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
175
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
176
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
177
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
178
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
179
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
180
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
181
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
182
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
183
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
184
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
185
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
186
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
187
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
188
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
189
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
190
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
191
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
192
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
193
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
194
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
195
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
196
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
197
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
198
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
199
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
200
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
201
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
202
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
203
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
204
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
205
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
206
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
207
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
208
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
209
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
210
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
211
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
212
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
213
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
214
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
215
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
216
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
217
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
218
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
219
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
220
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
221
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
222
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
223
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
224
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
225
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
226
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
227
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
228
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
229
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
230
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
231
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
232
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
233
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
234
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
c, 文件字符的绘制究竟是在何处?
答:在TextView.cs中的public override void Paint(Graphics g, Rectangle rect)函数中,重要函数:PaintLinePart(),辅助绘制函数:DrawDocumentWord(), DrawBracketHighlight(), DrawSpaceMarker(), DrawVerticalRuler() 等
d, 括号匹配在何处被定义和捕捉更新?
答:TextArea.cs中的List<BracketHighlightingSheme> bracketshemes = new List<BracketHighlightingSheme>();变量存储在查找的匹配项,SearchMatchingBracket()方法中搜索并更新匹配项的显示,相关代码如下:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
1
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
5
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
6
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
7
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
8
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
9
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
12
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
13
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
14
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
15
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
16
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
17
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
18
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
19
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
20
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
21
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
22
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
23
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
24
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
25
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
26
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
27
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
28
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
29
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
30
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
31
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
32
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
33
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
34
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
35
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
36
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
37
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
38
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
39
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
40
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
41
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
42
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
43
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
44
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
45
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
46
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
47
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
48
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
49
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
50
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
51
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
52
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
53
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
54
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
55
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
56
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
57
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
58
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
59
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
60
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
7、待分析的部分
本篇讨论暂未涉及如下(有价值?)内容的分析:
SyntaxHighlighting实现分析
BookmarkManager, FoldingManager, FormattingManager等
Paint()处理中坐标分析及转换