我有RichTextBox控件的选择问题。如果控件包含隐藏文本,则选择行为奇怪。
问题如下:假设我的控件有这样的文字:
有一个很小的升级控制,希望能成为一个 隐藏文字的原因是什么
然后假设我们通过应用正确的RTF标记来隐藏单词upgraded, hopefully, hidden
:
@"{\rtf1\ansi\ansicpg1252\deff0\deflang2057{\fonttbl{\f0\fnil\fcharset0 Microsoft Sans Serif;}} \viewkind4\uc1\pard\f0\fs17 There is the little \v upgraded \v0 control that \v hopefully \v0 will make a differnce when it is \v hidden \v0 text the reason\par}";
一切看起来都不错,但是当用户尝试使用键盘选择文本时,每次到达隐藏单词时,选择似乎都会重置。
对于我的控件来说,包含隐藏文本是至关重要的(来自控件内部形成内容的对象的一些重要id被存储为特殊位置的隐藏文本,我不能/不想改变这一点)。
答案 0 :(得分:0)
我正在使用以下Form
,其中richTextBox
是有问题的RichTextBox
而RichTextBox_SelectionChanged
是我们将尝试使用的SelectionChanged event处理程序解决我们的问题。
public MainForm()
{
InitializeComponent();
this.richTextBox.Rtf =
@"{\rtf1\ansi\ansicpg1252\deff0\deflang2057{\fonttbl{\f0\fnil\fcharset0 Microsoft Sans Serif;}}\viewkind4\uc1\pard\f0\fs17 My \v upgraded \v0 control that \v hopefully \v0 will make it\par}";
this.richTextBox.SelectionChanged += RichTextBox_SelectionChanged;
}
基本上,这个想法很简单 - 使用SelectionChanged
处理程序正确Select隐藏数据与之前的选择一起。
为此,我们必须存储以前的选择数据:
private class SelectionData
{
public static SelectionData FromStartAndEnd(
Int32 start,
Int32 end)
{
return new SelectionData(
start: start,
length: end - start);
}
public SelectionData(TextBoxBase tb)
: this(
start: tb.SelectionStart,
length: tb.SelectionLength)
{ }
public SelectionData(Int32 start, Int32 length)
{
this.Start = start;
this.Length = length;
}
public readonly Int32 Start, Length;
public Int32 End
{
get
{
return this.Start + this.Length;
}
}
}
在某些领域:
private SelectionData _previousSelection;
在SelectionChanged
hanlder
private void RichTextBox_SelectionChanged(object sender, EventArgs e)
{
var newSelection = new SelectionData(this.richTextBox);
this.SelfUpdateSelection(newSelection);
}
SelfUpdateSelection
方法类似于:
private Boolean _isSelectionSelfUpdating = false;
private void SelfUpdateSelection(SelectionData newSelection)
{
if (!this.IsKeyBoardSelection())
{
// Or it will use previous selection when we don't need it.
this._previousSelection = null;
return;
}
if (this._isSelectionSelfUpdating)
return;
this._isSelectionSelfUpdating = true;
try
{
var fixedSelection = this.FixSelection(newSelection);
this.richTextBox.Select(
start: fixedSelection.Start,
length: fixedSelection.Length);
this._previousSelection = fixedSelection;
}
finally
{
this._isSelectionSelfUpdating = false;
}
}
为简单起见,{p> IsKeyBoardSelection
可能类似于以下内容,但正确检测选择更改源将更加困难:
private bool IsKeyBoardSelection()
{
// It may not be true, but usually close enough.
return Control.ModifierKeys.HasFlag(Keys.Shift);
}
FixSelection
方法应比较newSelection
是否为this._previousSelection
并创建包含SelectionData
,newSelection
和this._previousSelection
的新private SelectionData FixSelection(SelectionData newSelection)
{
if (this._previousSelection == null)
return newSelection;
var start = Math.Min(
newSelection.Start,
this._previousSelection.Start);
var end = Math.Max(
newSelection.End,
this._previousSelection.End);
return SelectionData.FromStartAndEnd(
start: start,
end: end);
}
它们之间的隐藏数据。
您可以使用以下内容:
FixSelection
但它:
this._previousSelection
添加一些额外的逻辑来修复。还需要一些额外的public MainForm()
{
...
this.richTextBox.LostFocus += RichTextBox_LostFocus;
}
private void RichTextBox_LostFocus(object sender, EventArgs e)
{
this._previousSelection = null;
}
处理(比如在FocusLost事件中重置它) - 有一些边缘情况,但仍然没有什么不可能。
RichTextBox
PS:为了简单起见,我已经使用字段和表单级处理程序在表单中实现了所有内容,但是通过一些努力,它可以被制作成可重用的东西(最坏的派生RichTextBox
,最好是一些外部组件,它将为manifestPlaceholders
)提供这样的处理。