主要目的是让用户在所有其他选择的单词或短语中,确定一个选择是当前的。
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
if (results.Count > 0)
{
richTextBox1.SelectionStart = results[(int)numericUpDown1.Value - 1];
richTextBox1.SelectionLength = textBox1.Text.Length;
richTextBox1.SelectionColor = Color.Red;
richTextBox1.ScrollToCaret();
}
}
在这种情况下,在截图中,有3个搜索词的结果。System
. 所有的结果都是黄色的。
如果我把NumericUpDown的值改为2,那么第二个结果就会变成红色。System
然后当把NumericUpDown的值改为3时,它也会把最后一个系统结果染成红色。
我的问题是,2和3都会被染成红色。我只想让当前选中的单词被染成红色 其他的匹配结果应该使用默认颜色。
一些建议可以帮助构建一个能够处理文本选择的类对象。
这个类应该包含大部分(或全部)逻辑,以搜索给定文本中的关键字,维护所找到的匹配列表,它们的位置和长度,并允许基本的搜索。导航 的列表,以及其他配置,可以不费吹灰之力地扩展功能。
在这里 TextSearcher
1 类构造函数期望一个RichTextBox控件作为参数之一,加上一个用于正常选择的颜色和一个用于在匹配列表中突出显示当前匹配的颜色。航行.
► 搜索功能由 Regex.Matches() 方法,返回一个 MatchCollection 的 匹配 对象,相当方便,因为每个 Match
包含的位置(Index
属性),以及它的长度(Length
属性)。)
► 导航功能是由一个叫做 绑定源 对象。其 DataSource
属性设置为 MatchCollection
所回 Regex.Matches()
而且每次搜索新的关键字集时,它都会被重置。这个类在初始化时,提供了 MoveNext()
, MovePrevious()
, MoveLast()
和 MoveFirst()
方法,加上一个 Position
属性,它标识了集合中当前对象的索引--一个 Match
对象,这里。
► The CaseSensite
属性用于执行大小写敏感或不敏感的搜索。添加的目的是为了表明可以简单的扩展基本功能,在现有的基础上增加更多的功能(例如,文化敏感搜索)。
要初始化TextSearcher类,需要传递一个RichTextBox控件的实例和两个Color值到它的反构器中。
TextSearcher matchFinder = null;
public SomeForm()
{
InitializeComponent();
matchFinder = new TextSearcher(richTextBox1, Color.Yellow, Color.Red);
}
在这个例子中,你可以看到四个控件。
btnPrevious
)和下一个(btnNext
)按钮,用于浏览匹配列表。 nudGotoMatch
),用于跳转到一个特定的匹配的键程。 txtSearch
),用于输入一个或多个关键字,用管道隔开(管道字符用于在Regex中指定备用匹配,在用户界面中可以用其他东西代替)。 由于 TextSearcher
类包含了所有的搜索和导航逻辑,在前端激活这些控件的功能所需的代码是最小的,只是标准的UI要求(如设置 e.SuppressKeyPress = true
当在TextBox控件中按下Enter键时)。)
private void txtSearch_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter) {
string keywords = (sender as Control).Text;
e.SuppressKeyPress = true;
if (!matchFinder.CurrentKeywords.Equals(keyword)) {
nudGotoMatch.Maximum = matchFinder.Search(keywords);
}
}
}
private void nudGotoMatch_ValueChanged(object sender, EventArgs e)
{
if (matchFinder.Matches.Count > 0) {
matchFinder.GotoMatch((int)nudGotoMatch.Value - 1);
}
}
private void btnPrevious_Click(object sender, EventArgs e)
{
matchFinder.PreviousMatch();
}
private void btnNext_Click(object sender, EventArgs e)
{
matchFinder.NextMatch();
}
这就是它的工作原理。
控件的 TextSearcher
班上。
using System.Collections.Generic;
using System.Drawing;
using System.Text.RegularExpressions;
using System.Windows.Forms;
private class TextSearcher
{
private BindingSource m_bsMatches = null;
private RichTextBox m_Rtb = null;
public TextSearcher(RichTextBox rtb) : this(rtb, Color.Yellow, Color.Red) { }
public TextSearcher(RichTextBox rtb, Color selectionColor, Color currentColor)
{
this.m_Rtb = rtb;
SelectionColor = selectionColor;
CurrentColor = currentColor;
}
public string CurrentKeywords { get; private set; } = string.Empty;
public bool CaseSensitive { get; set; } = true;
public int CurrentIndex => m_bsMatches.Position;
public Match CurrentMatch => (Match)m_bsMatches.Current;
public MatchCollection Matches { get; private set; }
public Color SelectionColor { get; set; }
public Color CurrentColor { get; set; }
public void GotoMatch(int position)
{
SelectText(false);
this.m_bsMatches.Position = Math.Max(Math.Min(this.m_bsMatches.Count, position), 0);
SelectText(true);
}
public void NextMatch()
{
SelectText(false);
if (this.m_bsMatches != null && m_bsMatches.Position == this.m_bsMatches.Count - 1) {
this.m_bsMatches.MoveFirst();
}
else { this.m_bsMatches.MoveNext(); }
SelectText(true);
}
public void PreviousMatch()
{
SelectText(false);
if (this.m_bsMatches != null && this.m_bsMatches.Position > 0) {
this.m_bsMatches.MovePrevious();
}
else { this.m_bsMatches.MoveLast(); }
SelectText(true);
}
public int Search(string keywords)
{
if (CurrentKeywords.Equals(keywords)) return Matches.Count;
this.m_bsMatches?.Dispose();
CurrentKeywords = keywords;
var options = RegexOptions.Multiline |
(CaseSensitive ? RegexOptions.IgnoreCase : RegexOptions.None);
Matches = Regex.Matches(this.m_Rtb.Text, keywords, options);
if (Matches != null) {
this.m_Rtb.SelectAll();
this.m_Rtb.SelectionColor = this.m_Rtb.ForeColor;
this.m_Rtb.SelectionStart = 0;
this.m_bsMatches = new BindingSource(Matches, null);
SelectKeywords();
return Matches.Count;
}
return 0;
}
private void SelectKeywords()
{
foreach (Match m in Matches) {
SelectText(false);
NextMatch();
}
this.m_bsMatches.MoveFirst();
}
private void SelectText(bool current)
{
this.m_Rtb.Select(CurrentMatch.Index, CurrentMatch.Length);
this.m_Rtb.SelectionColor = current ? CurrentColor : SelectionColor;
}
}
我知道,好名字!我花了好长时间才想出来的,所以,请不要改:)