我刚刚碰到了同样的问题,现在我用EM_EXSETSEL解决了这个问题。当cpMin>cpMax时,它的工作方式类似于“反向选择”(在选定文本的开头插入符号)。然而,我还没有找到任何其他方法来找出当前的选择方向(EM_EXGETSEL总是返回cpMin<cpMax),但是在选择开始/长度更改之后。。。
编辑:
这就是我用来解决这个问题的。也许有一些更简单的方法,但至少下面的方法对我有用。
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
public struct CHARRANGE
{
public int cpMin;
public int cpMax;
}
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, ref CHARRANGE lParam);
private const UInt32 WM_USER = 0x0400;
private const UInt32 EM_EXSETSEL = WM_USER + 55;
private const UInt32 EM_EXGETSEL = WM_USER + 52;
private bool richTextBox1_SelectionChanged_lock = false;
private void richTextBox1_SelectionChanged(object sender, EventArgs e)
{
if (richTextBox1_SelectionChanged_lock) return;
richTextBox1_SelectionChanged_lock = true;
TrackRTBSelection(richTextBox1.SelectionStart, richTextBox1.SelectionLength);
SetRTBSelectionBasedOnTracking();
richTextBox1_SelectionChanged_lock = false;
}
private void buttonSetForeColor_Click(object sender, EventArgs e)
{
if (colorDialog1.ShowDialog() == DialogResult.Cancel)
return;
if (richTextBox1_SelectionChanged_lock) return;
richTextBox1_SelectionChanged_lock = true;
int selStart = richTextBox1.SelectionStart;
int selLength = richTextBox1.SelectionLength;
for (int i = 0; i < selLength; i++)
{
richTextBox1.SelectionLength = 1;
richTextBox1.SelectionStart = selStart + i;
richTextBox1.SelectionColor = colorDialog1.Color;
}
SetRTBSelectionBasedOnTracking();
richTextBox1_SelectionChanged_lock = false;
}
private bool caretPosition = false;
private int lastSelectionStart = -1;
private int lastSelectionLength = -1;
private void InitRTBSelection()
{
richTextBox1.SelectionStart = 0;
richTextBox1.SelectionLength = 0;
caretPosition = false;
lastSelectionStart = 0;
lastSelectionLength = 0;
richTextBox1_SelectionChanged(richTextBox1, new EventArgs());
}
private void TrackRTBSelection(int newSelectionStart, int newSelectionLength)
{
int condition = 0;
int s_change = (newSelectionStart - lastSelectionStart > 0) ?
1 :
(newSelectionStart - lastSelectionStart < 0) ? -1 : 0;
int l_change = (newSelectionLength - lastSelectionLength > 0) ?
1 :
(newSelectionLength - lastSelectionLength < 0) ? -1 : 0;
condition = (newSelectionLength == 0 ||
(l_change == 1 && s_change == -1) ||
(l_change == -1 && s_change == 1 && caretPosition == false)) ? 1 : condition;
condition = (s_change == 0 && (l_change == 1 || (caretPosition == true && l_change == -1))) ? 2 : condition;
switch (condition)
{
case 1: caretPosition = false; break;
case 2: caretPosition = true; break;
default: break;
}
lastSelectionStart = newSelectionStart;
lastSelectionLength = newSelectionLength;
}
private void SetRTBSelectionBasedOnTracking()
{
CHARRANGE chrrange = new CHARRANGE
{
cpMin = caretPosition ? lastSelectionStart : lastSelectionStart + lastSelectionLength,
cpMax = caretPosition ? lastSelectionStart + lastSelectionLength : lastSelectionStart
};
SendMessage(richTextBox1.Handle, EM_EXSETSEL, IntPtr.Zero, ref chrrange);
}