近来,由于某个项目的需求,朋友托我做了个数据库小助手,功能很简单,主要是通过这个工具将数据表结构以HTML或者XML文件方式导出。
可是做出来后,觉得这个工具功能太过简单了,于是就想着添加些功能上去,如查询显示数据库里的视图和存储过程等,如下图所示:
我是用RichTextBox空间来显示存储过程的,不过在RichTextBox上显示的过于直白,关键没有着色,看上去觉得不怎么好看,而且很烦人。
于是我想:RichTextBox能不能实现关键字高亮着色呢?
如果是在WinForm中很简单(网上搜的):


{
int nSelectStart = control.SelectionStart;
int nSelectLength = control.SelectionLength;
int nIndex = 0 ;
while (nIndex < control.Text.Length)
{
nIndex = control.Find(hilightString, nIndex, RichTextBoxFinds.WholeWord);
if (nIndex < 0 )
{
break ;
}
control.Select(nIndex, hilightString.Length);
control.SelectionColor = Color.Red;
nIndex += hilightString.Length;
}
control.Select(nSelectStart, nSelectLength);
}
可是,在WPF中RichTextBox没有Find函数 ,也没用SelectionColor等函数,怎么办?
于是我再翻过来,在MSDN上看看RichTextBox的结构,发现了RichTextBox内容是基于Document.FlowDirection的,可以通过TextPointer来确定要着色关键字的位置,然后在TextRange里的ApplyPropertyValue方法可以修改颜色。
如下代码:


{
// 设置文字指针为Document初始位置
// richBox.Document.FlowDirection
TextPointer position = richBox.Document.ContentStart;
while (position != null )
{
// 向前搜索,需要内容为Text
if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
{
// 拿出Run的Text
string text = position.GetTextInRun(LogicalDirection.Forward);
// 可能包含多个keyword,做遍历查找
int index = 0 ;
while (index < text.Length)
{
index = text.IndexOf(keyword, index);
// MessageBox.Show(index.ToString());
if (index == - 1 )
{
break ;
}
else
{
// 添加为新的Range
TextPointer start = position.GetPositionAtOffset(index);
TextPointer end = start.GetPositionAtOffset(keyword.Length);
TextPointer end1 = start.GetPositionAtOffset(index + keyword.Length);
selecta(l,richBox,keyword.Length, start, end);
index += keyword.Length;
}
}
}
// 文字指针向前偏移
position = position.GetNextContextPosition(LogicalDirection.Forward);
}
}
其中,改变关键字颜色的函数:


{
TextRange range = richTextBox1.Selection;
range.Select(tpStart, tpOffset);
// 高亮选择
if (l == " blue " ){
range.ApplyPropertyValue(TextElement.ForegroundProperty,
new SolidColorBrush(Colors.Blue));
range.ApplyPropertyValue(TextElement.FontWeightProperty,
FontWeights.Bold);
}
TextPointer position = richTextBox1.Document.ContentStart;
TextPointer start = position.GetPositionAtOffset( 2 );
TextPointer end = richTextBox1.Document.ContentEnd;
TextRange range1 = richTextBox1.Selection;
range1.Select(end, end);
range1.ApplyPropertyValue(TextElement.ForegroundProperty,
new SolidColorBrush(Colors.Black));
}
再定义个关键字数组:


{ // union all @ as varchar [ ] .column_id sys.indexes sys.index_columns
string [] res = { " ADD " , " EXISTS " , " PRECISION " , " ALL " , " EXIT " , " PRIMARY " , " ALTER " , " EXTERNAL " ,
" PRINT " , " FETCH " , " PROC " , " ANY