.net - Создание WinForms TextBox ведет себя как адресная строка вашего браузера




user-interface (20)

SelectAll никогда не работал для меня.

Это работает.

ActiveControl = textBox1;
textBox1->SelectionStart = 0;
textBox1->SelectionLength = textBox1->Text->Length;

Когда текстовое поле C # WinForms получает фокус, я хочу, чтобы он вел себя как адресная строка вашего браузера.

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

  1. Щелчок в текстовом поле должен выбрать весь текст, если текстовое поле ранее не было сфокусировано.
  2. Мышь вниз и перетаскивание в текстовое поле должны выбирать только текст, который я выделил с помощью мыши.
  3. Если текстовое поле уже сфокусировано, щелчок не отображает весь текст.
  4. Фокусировка текстового поля программно или с помощью клавиатуры позволяет выбрать весь текст.

Я хочу сделать именно это в WinForms.

БЫСТРЫЙ ПРЕДУПРЕЖДЕНИЕ ОШИБОК: перед тем, как ответить, прочитайте следующее. Спасибо, парни. :-)

Вызов .SelectAll () во время событий .Enter или .GotFocus не будет работать, потому что если пользователь щелкнул текстовое поле, каретка будет помещена туда, где он щелкнул, отменив выбор всего текста.

Вызов .SelectAll () во время события .Click не будет работать, потому что пользователь не сможет выбрать какой-либо текст с помощью мыши; вызов .SelectAll () будет переписывать текст пользователя.

Вызов BeginInvoke ((Action) textbox.SelectAll) при вводе фокуса / ввода события не работает, потому что он нарушает правило № 2 выше, он будет удерживать приоритет выбора пользователя в фокусе.


Ваше решение хорошо, но не в одном конкретном случае. Если вы даете фокус TextBox, выбирая диапазон текста, а не просто щелкнув, флаг ужеFocussed не получает значение true, поэтому при повторном щелчке в TextBox весь текст выбирается.

Вот моя версия решения. Я также поместил код в класс, который наследует TextBox, поэтому логика красиво скрыта.

public class MyTextBox : System.Windows.Forms.TextBox
{
    private bool _focused;

    protected override void OnEnter(EventArgs e)
    {
        base.OnEnter(e);
        if (MouseButtons == MouseButtons.None)
        {
            SelectAll();
            _focused = true;
        }
    }

    protected override void OnLeave(EventArgs e)
    {
        base.OnLeave(e);
        _focused = false;
    }

    protected override void OnMouseUp(MouseEventArgs mevent)
    {
        base.OnMouseUp(mevent);
        if (!_focused)
        {
            if (SelectionLength == 0)
                SelectAll();
            _focused = true;
        }
    }
}


Для группы текстовых полей в форме:

private System.Windows.Forms.TextBox lastFocus;   

private void textBox_GotFocus(object sender, System.Windows.Forms.MouseEventArgs e)   
{
    TextBox senderTextBox = sender as TextBox;
    if (lastFocus!=senderTextBox){
        senderTextBox.SelectAll();
    }
    lastFocus = senderTextBox;   
}

Интересно, что ComboBox с DropDownStyle = Simple имеет в точности то же самое поведение, которое вы ищете, я думаю.

(Если вы уменьшите высоту элемента управления, чтобы не показывать список, а затем на пару пикселей больше - нет эффективной разницы между ComboBox и TextBox.)


Кажется, что это работает. Событие ввода обрабатывает вкладку в элемент управления, а MouseDown работает при нажатии элемента управления.

    private ########### void textBox1_Enter(object sender, EventArgs e)
    {
        textBox1.SelectAll();
    }

    private void textBox1_MouseDown(object sender, MouseEventArgs e)
    {
        if (textBox1.Focused)
            textBox1.SelectAll();
    }

Нажмите событие текстового поля? Или даже событие MouseCaptureChanged работает для меня. - ОК. не работает.

Поэтому вам нужно сделать 2 вещи:

private bool f = false;

private void textBox_MouseClick(object sender, MouseEventArgs e)
{ 
  if (this.f) { this.textBox.SelectAll(); }
  this.f = false;
}

private void textBox_Enter(object sender, EventArgs e)
{
  this.f = true;
  this.textBox.SelectAll();
}
private void textBox_MouseMove(object sender, MouseEventArgs e) // idea from the other answer
{
  this.f = false; 
}

Работает для табуляции (через textBoxes к одному) - call SelectAll () в Enter на всякий случай ...


Настройте выделение, когда вы оставите элемент управления. Он будет там, когда вы вернетесь. Вкладка вокруг формы и когда вы вернетесь к элементу управления, будет выбран весь текст.

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

private void maskedTextBox1_Leave(object sender, CancelEventArgs e)
    {
        maskedTextBox1.SelectAll();
    }

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

В поле ввода:

txtFilter.BeginInvoke (новый MethodInvoker (txtFilter.SelectAll));


Очень простое решение:

    private bool _focusing = false;

    protected override void OnEnter( EventArgs e )
    {
        _focusing = true;
        base.OnEnter( e );
    }

    protected override void OnMouseUp( MouseEventArgs mevent )
    {
        base.OnMouseUp( mevent );

        if( _focusing )
        {
            this.SelectAll();
            _focusing = false;
        }
    }

EDIT: Original OP особенно беспокоился о последовательности мыши-мыши / выбора текста / мыши, и в этом случае вышеуказанное простое решение закончится тем, что текст будет частично выбран.

Это должно решить * проблему (на практике я перехватываю WM_SETCURSOR):

    protected override void WndProc( ref Message m )
    {
        if( m.Msg == 32 ) //WM_SETCURSOR=0x20
        {
              this.SelectAll(); // or your custom logic here                
        }

        base.WndProc( ref m );
    }

* На самом деле следующая последовательность заканчивается частичным выбором текста, но затем, если вы переместите мышь над текстовым полем, весь текст будет выбран снова:

mouse-down / text-selection / mouse-move-out-textbox / mouse-up


Прежде всего, спасибо за ответы! 9 ответов. Спасибо.

Плохие новости: все ответы имели некоторые причуды или не работали совершенно правильно (или вообще). Я добавил комментарий к каждому из ваших сообщений.

Хорошие новости: я нашел способ заставить его работать. Это решение довольно просто и, кажется, работает во всех сценариях (выключение, выбор текста, фокус табуляции и т. Д.),

bool alreadyFocused;

...

textBox1.GotFocus += textBox1_GotFocus;
textBox1.MouseUp += textBox1_MouseUp;
textBox1.Leave += textBox1_Leave;

...

void textBox1_Leave(object sender, EventArgs e)
{
    alreadyFocused = false;
}


void textBox1_GotFocus(object sender, EventArgs e)
{
    // Select all text only if the mouse isn't down.
    // This makes tabbing to the textbox give focus.
    if (MouseButtons == MouseButtons.None)
    {
        this.textBox1.SelectAll();
        alreadyFocused = true;
    }
}

void textBox1_MouseUp(object sender, MouseEventArgs e)
{
    // Web browsers like Google Chrome select the text on mouse up.
    // They only do it if the textbox isn't already focused,
    // and if the user hasn't selected all text.
    if (!alreadyFocused && this.textBox1.SelectionLength == 0)
    {
        alreadyFocused = true;
        this.textBox1.SelectAll();
    }
}

Насколько я могу судить, это приводит к тому, что текстовое поле ведет себя точно так же, как адресная строка веб-браузера.

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

Еще раз спасибо, ребята, за все ваши ответы, которые помогли привести меня к правильному пути.


Просто выведите класс из TextBox или MaskedTextBox:

public class SMaskedTextBox : MaskedTextBox
{
    protected override void OnGotFocus(EventArgs e)
    {
        base.OnGotFocus(e);
        this.SelectAll();
    }
}

И используйте его на своих формах.


Это немного kludgey, но в вашем событии click используйте SendKeys.Send( "{HOME}+{END}" ); ,


Это похоже на популярный ответ nzhenry, но мне легче не иметь подкласса:

    Private LastFocused As Control = Nothing

Private Sub TextBox1_Enter(sender As Object, e As System.EventArgs) Handles TextBox1.Enter, TextBox2.Enter, TextBox3.Enter
    If MouseButtons = Windows.Forms.MouseButtons.None Then LastFocused = sender
End Sub

Private Sub TextBox1_Leave(sender As Object, e As System.EventArgs) Handles TextBox1.Leave, TextBox2.Leave, TextBox3.Leave
    LastFocused = Nothing
End Sub

Private Sub TextBox1_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseUp, TextBox2.MouseUp, TextBox3.MouseUp
    With CType(sender, TextBox)
        If LastFocused IsNot sender AndAlso .SelectionLength = 0 Then .SelectAll()
    End With
    LastFocused = sender
End Sub

Это работало в текстовом поле WPF / XAML TextBox.

    private bool initialEntry = true;
    private void TextBox_SelectionChanged(object sender, RoutedEventArgs e)
    {
        if (initialEntry)
        {
            e.Handled = true;
            initialEntry = false;
            TextBox.SelectAll();
        }
    }
    private void TextBox_GotFocus(object sender, RoutedEventArgs e)
    {
        TextBox.SelectAll();
        initialEntry = true;      
    }

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

В событии мыши все, что вам нужно сделать, это место

if(textBox.SelectionLength = 0)
{
    textBox.SelectAll();
}

Кажется, это работает для меня в VB.NET (я знаю, что это вопрос C # ... К сожалению, я вынужден использовать VB на моей работе .. и у меня была эта проблема, и именно это привело меня сюда ... )

Я еще не нашел никаких проблем с этим, кроме того, что он не сразу выбирает по щелчку, но у меня были проблемы с этим ....


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

    private bool SearchBoxInFocusAlready = false;
    private void SearchBox_LostFocus(object sender, RoutedEventArgs e)
    {
        SearchBoxInFocusAlready = false;
    }

    private void SearchBox_PreviewMouseUp(object sender, MouseButtonEventArgs e)
    {
        if (e.ButtonState == MouseButtonState.Released && e.ChangedButton == MouseButton.Left &&
            SearchBox.SelectionLength == 0 && SearchBoxInFocusAlready == false)
        {
            SearchBox.SelectAll();
        }

        SearchBoxInFocusAlready = true;
    }

Я нашел более простое решение этого. Это включает асинхронное отключение SelectAll с помощью Control.BeginInvoke чтобы оно происходило после возникновения событий Enter и Click:

В C #:

private void MyTextBox_Enter(object sender, EventArgs e)
{
    // Kick off SelectAll asyncronously so that it occurs after Click
    BeginInvoke((Action)delegate
    {
        MyTextBox.SelectAll();
    });
}

В VB.NET (спасибо Кришану Дей )

Private Sub MyTextBox_Enter(sender As Object, e As EventArgs) Handles MyTextBox.Enter 
    BeginInvoke(DirectCast(Sub() MyTextBox.SelectAll(), Action)) 
End Sub

просто используйте selectall () для ввода и нажмите события

private void textBox1_Enter(object sender, EventArgs e)
        {

            textBox1.SelectAll();
        }
        private void textBox1_Click(object sender, EventArgs e)
        {
            textBox1.SelectAll();
        }

'Inside the Enter event
TextBox1.SelectAll();

Хорошо, попробовав это, вот что вам нужно:

  • В поле «Ввод» введите флаг, в котором указано, что вы были в событии ввода
  • В событии Click, если вы установили флаг, вызовите .SelectAll () и сбросьте флаг.
  • В событии MouseMove установите для введенного флага значение false, которое позволит вам щелкнуть выделение, не вставляя сначала текстовое поле.

Это отобразило весь текст при записи, но потом позволил мне выделить часть текста или вы можете выделить его при первом щелчке.

По запросу:

    bool entered = false;
    private void textBox1_Enter(object sender, EventArgs e)
    {
        entered = true;
        textBox1.SelectAll();   //From Jakub's answer.
    }

    private void textBox1_Click(object sender, EventArgs e)
    {
        if (entered) textBox1.SelectAll();
        entered = false;
    }

    private void textBox1_MouseMove(object sender, MouseEventArgs e)
    {
        if (entered) entered = false;
    }

Для меня вкладка в элемент управления выбирает весь текст.







textbox