Укажите поведение подсветки при двойном щелчке текстовой области или текстового поля? - PullRequest
7 голосов
/ 28 июня 2011

Я заметил, что многие приложения, которые ожидают от вас большого редактирования текста, будут обеспечивать поведение по умолчанию для двойного щелчка по тексту, поскольку приложение выделяет текст, с которым, по его мнению, вы, скорее всего, пытаетесь взаимодействовать.

В качестве быстрого примера, это предложение ведет себя по-разному в разных приложениях:

Это "примерное" предложение

Если я наберу это в Блокноте и дважды нажму на слово «образец» (в идеале середина слова, скажем, между «м» и «р» образца), то блокнот подсветится от первой кавычки до пробела после вторая цитата включительно. Если это предложение есть в комментарии в Visual Studio, и я дважды щелкаю в том же месте, оно выделяется от 's' до 'e' образца без выделения кавычек.

Как я могу настроить эти варианты подсветки в моем собственном приложении? Отличается ли он от winforms до WPF? Я полагаю, я мог бы взломать мой способ заставить его работать на событие двойного щелчка, но есть ли более элегантное / продуманное решение, предназначенное исключительно для этого?

Ответы [ 4 ]

3 голосов
/ 21 апреля 2015

Да, использование события DoubleClick для выполнения желаемых действий является неуместным, поскольку кажется, что оно выполняет выделение дважды, что медленнее, выглядит хуже и может вызвать нежелательные события / код.

Таким образом, приведенный ниже код должен помочь, по крайней мере, Winforms. Создайте новый класс и расширьте TextBox (или RichTextBox) обычным способом (используя только что созданный элемент управления, который должен волшебным образом появиться в конструкторе). Я сделал простую процедуру, в которой вы можете указать используемый разделитель. Приложив немного больше работы, должно быть легко учесть диапазон символов, а не только один, или даже создать другие более продвинутые способы выбора.

Если вы используете TextBox вместо RichTextBox, просто удалите бит «Rich», который дважды появляется в определении класса.

class RichTextBoxX : RichTextBox
{
    char delimiter = ',';   // Specify what character to use for start and end of selection

    protected override void WndProc(ref System.Windows.Forms.Message m)
    {
        if (m.Msg==0x0203) // WM_LBUTTONDBLCLK
        {
            // Perfect situation for off-by-one bugs! Checked thoroughly for at least 10 mins, so should be okay now:
            int start = this.SelectionStart;
            if (start < 1) start = 1;
            int left = this.Text.LastIndexOf(delimiter, start - 1);
            int right = this.Text.IndexOf(delimiter, start);
            if (right == -1) right = Text.Length;
            this.SelectionStart = left + 1;
            this.SelectionLength = right - left - 1;
            return;             
        }

        base.WndProc(ref m);
    }
}
1 голос
/ 19 октября 2018

Я использую Regex \w, который равен [a-zA-Z0-9_], чтобы заменить TextBox выделение

private void TextBox1_MouseDoubleClick(object sender, MouseEventArgs e)
{
    string text = TextBox1.SelectedText;
    var strA = Regex.Match(text, @"\w+");
    int indexA = TextBox1.SelectionStart + text.IndexOf(strA.Value);
    TextBox1.Select(indexA, strA.Value.Length);
}

оригинальный результат:

Это "sample" предложение

указанным выше методом

Это предложение "sample"

1 голос
/ 31 июля 2017

Улучшенный ответ от DarkPh03n1X почти работал для меня, однако у него есть неприятная ошибка: если символ разделителя не может быть найден , Text.IndexOf(c, start) вернет -1 который установит right в -1, а затем if (right == -1) right = Text.Length сработает.

Так что теперь мы выбрали до конца текста, хотя ожидаемый выбор должен быть короче. Думаю, старт сделан правильно.

Я удалил if (right == -1) right = Text.Length, но добавил && pos != -1. Вот исправленная версия:

class RichTextBoxX : RichTextBox
{
    // implement selection to work with "whole words" on double-click 
    // and without selecting the leading/trailing spaces/blanks/line breaks
    private char[] delimiterList = new[] { '\n', ',', ' ', '(', ')', '_', '/' };

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x0203) // WM_LBUTTONDBLCLK
        {
            int start = SelectionStart;
            if (start < 1) start = 1;

            int left = -1;
            int right = Text.Length;
            int pos;

            foreach (char c in delimiterList)
            {
                pos = Text.LastIndexOf(c, start - 1);
                if (pos > left) left = pos;

                pos = Text.IndexOf(c, start);
                if (pos < right && pos != -1) right = pos;
            }

            SelectionStart = left + 1;
            SelectionLength = right - left - 1;
            return;
        }

        base.WndProc(ref m);
    }
}

Чтобы проверить поведение, вот пример текста, который я использовал:

12.34.56.78  (ab1-2-3-4-5.test-1.example.com)
Jersey City
New Jersey
US, United States
ASN: Example.com/12345

Я добавил несколько других разделителей, не стесняйтесь выбирать, что вам нужно.

0 голосов
/ 01 декабря 2016

Добавляя к работе DanW, я добавил несколько разделителей, которые, кажется, хорошо работают.

class RichTextBoxX : RichTextBox
{
    private char[] delimiterList = new[] { ',', ' '};

    protected override void WndProc(ref System.Windows.Forms.Message m)
    {
        if (m.Msg == 0x0203) // WM_LBUTTONDBLCLK
        {
            int start = this.SelectionStart;
            if (start < 1) start = 1;

            int left = -1;
            int right = Text.Length;

            foreach (char c in delimiterList)
            {
                if (this.Text.LastIndexOf(c, start - 1) > left)
                {
                    left = this.Text.LastIndexOf(c, start - 1);
                }

                if (this.Text.IndexOf(c, start) < right)
                {
                    right = this.Text.IndexOf(c, start);
                    if (right == -1) right = Text.Length;
                }
            }

            this.SelectionStart = left + 1;
            this.SelectionLength = right - left - 1;
            return;
        }

        base.WndProc(ref m);
    }
}

Еще одна вещь: чтобы внедрить вставленный выше код в «код» вашей формы, на котором вы собираетесь его использовать, теперь используйте «Дизайнер форм», чтобы перетащить RichTextBox на вашу форму, теперь перейдите к форме конструктор класса в моем случае form1.desigener.cs и найти строку реализации, например:

this.richTextBox1 = new System.Windows.Forms.RichTextBox();

и замените его на

this.richTextBox1 = new project.form1.RichTextBoxX();

После этого этот элемент управления будет работать как обычная реализация RichTextBox с функцией дополнительного оверида

...