Je viens de frapper le même problème et maintenant j'ai résolu cela en utilisant EM_EXSETSEL. Quand cpMin> cpMax, cela fonctionne comme "sélection vers l'arrière" (caret au début du texte sélectionné). Pourtant, je ne l'ai pas trouvé d'autre moyen de savoir la direction de la sélection actuelle (EM_EXGETSEL toujours retourné CPmin < CPmax), mais suite à des changements SelectionStart/longueur ...
EDIT:
C'est ce que j'utilise pour résoudre ce. Il pourrait y avoir un moyen plus facile, mais au moins les travaux suivants pour moi.
using System.Runtime.InteropServices;
//********************
//SendMessage stuff for EM_EXSETSEL
//********************
[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;
//********************
//event handlers
//********************
//locking variable to avoid stack overflow while setting selection in code
private bool richTextBox1_SelectionChanged_lock = false;
//handler for richTextBox selection change event
private void richTextBox1_SelectionChanged(object sender, EventArgs e)
{
if (richTextBox1_SelectionChanged_lock) return;
richTextBox1_SelectionChanged_lock = true;
//detect selection changes and store information needed for restoring
TrackRTBSelection(richTextBox1.SelectionStart, richTextBox1.SelectionLength);
//here do whatever you want with selection (some analysis to show font name in font selection comboBox etc.)
//...
//restore selection from saved informations
SetRTBSelectionBasedOnTracking();
richTextBox1_SelectionChanged_lock = false;
}
//sample button click handler for changing fore color of selected text
private void buttonSetForeColor_Click(object sender, EventArgs e)
{
if (colorDialog1.ShowDialog() == DialogResult.Cancel)
return;
//prevent selection change events while we are changing font colors
if (richTextBox1_SelectionChanged_lock) return;
richTextBox1_SelectionChanged_lock = true;
//save selection parameters for use in loop
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;
}
//restore selection from saved informations
SetRTBSelectionBasedOnTracking();
richTextBox1_SelectionChanged_lock = false;
}
//********************
//selection tracking utilities
//********************
//false - caret at the beginning; true - caret at the end
private bool caretPosition = false;
private int lastSelectionStart = -1;
private int lastSelectionLength = -1;
//initialize selection informations. this must be called during Form_Load
private void InitRTBSelection()
{
richTextBox1.SelectionStart = 0;
richTextBox1.SelectionLength = 0;
caretPosition = false;
lastSelectionStart = 0;
lastSelectionLength = 0;
//force "selection changed" to detect "selection changes" for the first time
richTextBox1_SelectionChanged(richTextBox1, new EventArgs());
}
//this method detects changes in selection, based on selection parameters received from richTextBox
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;
//these conditions where created over change table for all user-achievable scenarios
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; //if no condition was satisfied then maintain current information
}
lastSelectionStart = newSelectionStart;
lastSelectionLength = newSelectionLength;
}
//set richTextBox selection using EM_EXSETSEL
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);
}
Est-ce que cela a été résolu? Pour ma part, j'ai essayé d'envoyer rapidement des touches pour "Shift-Left" et "Shift-Right" pour déterminer la direction du mouvement et déterminer la "direction", mais le problème avec l'utilisation des touches est cette autre logique les événements sont appelés comme résultat. –
Je ne pense pas que je l'ai jamais fait, je pense que je viens d'utiliser un autre contrôle de mise en évidence syntaxique préconstruit qui était capable de le faire automatiquement. – Miguel