我使用以下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;
}
}
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
處理(就像在FocusLost事件重置它) - 有一些邊緣情況下,但仍然沒有什麼不可能的。
public MainForm()
{
...
this.richTextBox.LostFocus += RichTextBox_LostFocus;
}
private void RichTextBox_LostFocus(object sender, EventArgs e)
{
this._previousSelection = null;
}
PS:爲了簡單起見,我已經實現了一切與字段和表單級處理的形式內,但也有一些努力,也可以做成一些可重複使用的(在最壞的情況衍生RichTextBox
,充其量一些外部部件將爲RichTextBox
提供這種處理)。
你可以用乾淨的新項目重現問題嗎?我的意思是你可以爲這個問題創建一個[MCVE](http://stackoverflow.com/help/mcve)嗎? –
是的,它似乎很容易重現。我不認爲這是我的代碼中的錯誤,而是富文本框控件的行爲,或者控件本身內部的錯誤。 [在這裏你可以找到示例項目的錯誤](https://www.dropbox.com/s/sef62c2c2kt2ds2/rtbTest.zip?dl=0) 只需點擊文本的開始(第一個文本框內)它已經包含隱藏的內容,按住Shift並按下左箭頭,就像通常使用鍵盤選擇文本一樣。 選擇將在到達隱藏字時重置 – aleksandaril
您能否提供MCVE?我的意思是至少使用了RTF。只要檢查一下你是否可以用那個RTF的乾淨項目真正地複製它。 –