Frage

Wenn ein C # WinForms Textbox den Fokus erhält, möchte ich es wie das Browseradressleiste verhalten.

Um zu sehen, was ich meine, klicken Sie in der Adressleiste des Web-Browsers. Sie werden das folgende Verhalten fest:

  1. in das Textfeld ein Klicken auf alle sollten den Text auswählen, wenn die Textbox nicht vorher fokussiert war.
  2. Maus nach unten und ziehen Sie in der Textbox sollte nur den Text markieren ich mit der Maus markiert haben.
  3. Wenn das Textfeld bereits fokussiert, klicken wählen nicht den gesamten Text.
  4. Fokussierung der Textbox programmatisch oder über die Tastatur tabbing sollte den gesamten Text auswählen.

Ich will genau dies in WinForms tun.

Schnellste ALERT: bitte das folgende lesen, bevor er antwortete: Danke Jungs!. : -)

  

Der Aufruf .SelectAll () während   die .Enter oder .GotFocus Ereignisse nicht    arbeiten, weil, wenn der Benutzer geklickt hat die   Textbox, wird die caret platziert   wo er angeklickt, so Abwahl alle   Text.

     

aufrufen .SelectAll () während der .Click Ereignis wird nicht funktionieren , da der Benutzer nicht in der Lage sein, einen beliebigen Text mit der Maus auswählen; die .SelectAll () Aufruf der Textauswahl des Benutzers zu überschreiben halten.

     

aufrufen BeginInvoke ((Action) textbox.SelectAll) auf Fokus / Enter Ereignis eingeben funktioniert nicht , weil es Regel # 2 oben bricht, wird es halten Sie die Auswahl auf Fokus des Benutzers überschreiben.

War es hilfreich?

Lösung

Zunächst einmal vielen Dank für Antworten! 9 Antworten insgesamt. Danke.

Bad news: alle Antworten einige Macken hatte oder nicht ganz richtig arbeiten (oder überhaupt). Ich habe einen Kommentar zu jedem Ihrer Beiträge hinzugefügt.

Eine gute Nachricht: Ich habe einen Weg gefunden, es funktioniert. Diese Lösung ist ziemlich einfach und scheint in allen Szenarien zu arbeiten (mousing nach unten, Markieren von Text, Fokus Tabbing usw.)

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();
    }
}

Soweit ich das beurteilen kann, verursacht dies eine Textbox zu verhalten sich genau wie die Adresszeile des Web-Browsers.

Hoffentlich hilft der nächste Mann, der diese scheinbar einfache Problem zu lösen versucht.

Nochmals vielen Dank, Jungs, für alle Ihre Antworten, die mich auf dem richtigen Weg führen geholfen.

Andere Tipps

Ich fand eine einfachere Lösung dieses Problems. Es geht um den SelectAll asynchron mit Control.BeginInvoke tritt ab, so dass es nach der Eingabe und klicken Sie tritt Ereignisse eingetreten sind:

In C #:

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

In VB.NET (dank Krishanu Dey )

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

Ihre Lösung ist gut, aber nicht in einem konkreten Fall. Wenn Sie die TextBox Fokus geben, indem eine Reihe von Text auswählen, anstatt nur zu klicken, wird der alreadyFocussed Flag nicht auf true gesetzt bekommen, also, wenn Sie in dem Text ein zweites Mal klicken, wird der gesamte Text ausgewählt wird.

Hier ist meine Version der Lösung. Ich habe auch setzen Sie den Code in einer Klasse, die TextBox erbt, so die Logik weg gut versteckt ist.

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;
        }
    }
}

Es ist ein bisschen kludgey, aber in Ihrem Click-Ereignisse, verwendet SendKeys.Send( "{HOME}+{END}" );.

Klicken Sie auf Ereignis von Textbox? Oder auch Mousecapturechanged Ereignis funktioniert für mich. - OKAY. funktioniert nicht.

Sie haben also zwei Dinge zu tun:

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; 
}

Werke für Tabbing (durch Textfelder einer) als auch - nennen SelectAll () in Geben Sie für alle Fälle ...

A eine Zeile Antwort, die ich benutze ... Sie könnten sich tretend ...

Geben Sie im Feld Ereignisse:

txtFilter.BeginInvoke (neu MethodInvoker (txtFilter.SelectAll));

'Inside the Enter event
TextBox1.SelectAll();

Ok, nachdem es hier versuchen, ist, was Sie wollen:

  • Geben Sie auf dem Ereignis eine Flagge starten, die besagt, dass Sie in das Feld Ereignis gewesen
  • Auf dem Click-Ereignis, wenn Sie das Kennzeichen setzen, rufen .SelectAll () und das Flag zurückgesetzt.
  • Auf dem Mousemove-Ereignis, stellen Sie die eingegebene Flag auf False, die es Ihnen erlaubt Highlight zu klicken, ohne die Textbox zuerst eingeben zu müssen.

Das ausgewählte ganzen Text über den Eintritt, aber erlaubt mir später einen Teil des Textes zu markieren, oder können Sie sich auf den ersten Klick markieren.

Auf Anfrage:

    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;
    }

Für mich ist die Navigation mit der Tabulatortaste in die Steuerung wählt den gesamten Text.

Hier ist eine Hilfsfunktion, die Lösung für die nächste Stufe -. Wiederverwendung ohne Vererbung

    public static void WireSelectAllOnFocus( TextBox aTextBox )
    {
        bool lActive = false;
        aTextBox.GotFocus += new EventHandler( ( sender, e ) =>
        {
            if ( System.Windows.Forms.Control.MouseButtons == MouseButtons.None )
            {
                aTextBox.SelectAll();
                lActive = true;
            }
        } );

        aTextBox.Leave += new EventHandler( (sender, e ) => {
            lActive = false;
        } );

        aTextBox.MouseUp += new MouseEventHandler( (sender, e ) => {
            if ( !lActive )
            {
                lActive = true;
                if ( aTextBox.SelectionLength == 0 ) aTextBox.SelectAll();
            }   
        });
    }

Um dies nutzen Sie einfach die Funktion aufrufen, einen Text vorbei und es kümmert sich um alle chaotisch Bits für Sie. Ich schlage vor, die Verdrahtung alle Textfelder in der Form_Load-Ereignis auf. Sie können diese Funktion in Ihrem Formular platzieren, oder wenn Ihr wie ich, irgendwo in einer Utility-Klasse für noch mehr Wiederverwendung.

Das funktionierte für eine 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;      
    }

Dies ist vergleichbar mit nzhenry 's beliebter Antwort, aber ich finde es einfacher zu haben, um nicht eine Unterklasse:

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

SelectAll nie für mich gearbeitet.

Das funktioniert.

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

Ich habe eine noch einfachere Lösung gefunden:

Um sicherzustellen, dass der gesamte Text ausgewählt wird, wenn auf einem textBox klicken, stellen Sie sicher, dass die Click-Handler der Handler Geben Sie ruft. Keine Notwendigkeit für zusätzliche Variablen!

Beispiel:

private void textBox1_Click(object sender, EventArgs e){
        textBox1_Enter(sender, e);
    }

private void textBox1_Enter(object sender, EventArgs e){
        TextBox tb = ((TextBox)sender);
        tb.SelectAll();
    }
private bool _isSelected = false;
private void textBox_Validated(object sender, EventArgs e)
{
    _isSelected = false;
}

private void textBox_MouseClick(object sender, MouseEventArgs e)
{
    SelectAllText(textBox);
}

private void textBox_Enter(object sender, EventArgs e)
{
    SelectAllText(textBox);
}

private void SelectAllText(TextBox text)
{
    if (!_isSelected)
    {
        _isSelected = true;
        textBox.SelectAll();
    }
}

Interessanterweise eine ComboBox mit Dropdownstyle = Einfache hat so ziemlich genau das Verhalten, das Sie suchen, denke ich.

(Wenn Sie die Höhe der Steuer nicht zeigt die Liste zu reduzieren - und dann durch ein paar Pixel mehr -. Gibt es keine effektive Differenz zwischen dem ComboBox und dem Text)

Warum gehst du nicht einfach die MouseDown--Ereignis des Textfelds verwenden? Es funktioniert gut für mich und keinen zusätzlichen boolean benötigen. Sehr sauber und einfach, zB:.

private void textbox_MouseDown(object sender, MouseEventArgs e) {
    if (textbox != null && !string.IsNullOrEmpty(textbox.Text))
    {
        textbox.SelectAll();
    } }

Ich rief SelectAll innen MouseUp-Ereignis und es funktionierte gut für mich.

    private bool _tailTextBoxFirstClick = false;

    private void textBox1_MouseUp(object sender, MouseEventArgs e)
    {
        if(_textBoxFirstClick)           
            textBox1.SelectAll();

        _textBoxFirstClick = false;
    }  

    private void textBox1_Leave(object sender, EventArgs e)
    {
        _textBoxFirstClick = true;
        textBox1.Select(0, 0);
    }

ableiten doch einfach eine Klasse von TextBox oder MaskedTextBox:

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

Und verwenden Sie es auf Ihren Formularen.

Haben Sie versucht, schlug die Lösung auf der MSDN-Forum "Windows Forms General" die einfach TextBox Unterklassen?

Eigentlich ist GotFocus das richtige Ereignis (Nachricht wirklich), die Sie interessiert sind, da unabhängig davon, wie Sie auf die Kontrolle bekommen Sie dies auch schließlich bekommen. Die Frage ist, wann nennst du SelectAll ().

Versuchen Sie folgendes:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        this.textBox1.GotFocus += new EventHandler(textBox1_GotFocus);
    }

    private delegate void SelectAllDelegate();    
    private IAsyncResult _selectAllar = null; //So we can clean up afterwards.

    //Catch the input focus event
    void textBox1_GotFocus(object sender, EventArgs e)
    {
        //We could have gotten here many ways (including mouse click)
        //so there could be other messages queued up already that might change the selection.
        //Don't call SelectAll here, since it might get undone by things such as positioning the cursor.
        //Instead use BeginInvoke on the form to queue up a message
        //to select all the text after everything caused by the current event is processed.
        this._selectAllar = this.BeginInvoke(new SelectAllDelegate(this._SelectAll));
    }

    private void _SelectAll()
    {
        //Clean-up the BeginInvoke
        if (this._selectAllar != null)
        {
            this.EndInvoke(this._selectAllar);
        }
        //Now select everything.
        this.textBox1.SelectAll();
    }
}

Für eine Gruppe von Textfeldern in einer Form:

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;   
}

Das scheint unten zu arbeiten. Das Eingabe-Ereignis behandelt das tabbing an die Steuerung und die MouseDown- funktioniert, wenn die Steuerung angeklickt wird.

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

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

Ich weiß, das wurde bereits gelöst, aber ich habe einen Vorschlag, dass ich denke eigentlich ziemlich einfach ist.

In der Maus Veranstaltung alles, was Sie tun müssen, ist Platz

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

Es scheint für mich in VB.NET (Ich weiß, das ist eine C # Frage zu arbeiten ... leider bin ich gezwungen, VB an meinem Job zu verwenden .. und ich dieses Problem hatte, das, was mich hierher gebracht ...)

Ich habe keine Probleme mit ihm noch .. mit Ausnahme der Tatsache, dass es nicht sofort auf, klicken Sie nicht wählen, aber ich habe Probleme mit, dass ....

Die folgende Lösung funktioniert für mich. Ich habe OnKeyDown und OnKeyUp Ereignis überschreibt den TextBox Text zu halten immer ausgewählt.

    public class NumericTextBox : TextBox
{
    private bool _focused;
    protected override void OnGotFocus(EventArgs e)
    {
        base.OnGotFocus(e);
        if (MouseButtons == MouseButtons.None)
        {
            this.SelectAll();
            _focused = true;
        }
    }
    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;
        }
    }

    protected override void OnKeyUp(KeyEventArgs e)
    {
        base.OnKeyUp(e);

        if (SelectionLength == 0)
            SelectAll();
        _focused = true;
    }
    protected override void OnKeyDown(KeyEventArgs e)
    {
       base.OnKeyDown(e);
       if (SelectionLength == 0)
            SelectAll();
        _focused = true;
    }
}

Stellen Sie die selction, wenn Sie die Kontrolle verlassen. Es wird da sein, wenn Sie wieder zu bekommen. Tab rund um die Form und, wenn Sie an die Steuerung zurückkehren, der gesamte Text ausgewählt.

Wenn Sie mit der Maus hineingehen, dann wird das Caret zu Recht an der Stelle platziert werden, wo Sie geklickt haben.

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

Die Antwort kann eigentlich ganz einfacher sein als alle der oben genannten, zum Beispiel (in WPF):

public void YourTextBox_MouseEnter(object sender, MouseEventArgs e)
    {
        YourTextBox.Focus();
        YourTextBox.SelectAll();
    }

Natürlich kann ich nicht wissen, wie Sie diesen Code verwenden möchten, aber der Hauptteil an hier zu sehen ist: Zunächst rufen .Focus () und rufen Sie dann .SelectAll ();

Sehr einfache Lösung:

    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 war insbesondere besorgt über die Maus-down / Text-Auswahl / Maus-Sequenz, wobei in diesem Fall die obige einfache Lösung wäre am Ende mit Text teilweise ausgewählt werden

Dies sollte lösen * das Problem (in der Praxis ich abfangen 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 );
    }

* Tatsächlich ist die folgende Sequenz endet mit Teiltextauswahl, aber dann, wenn Sie die Maus über das Textfeld der gesamte Text ausgewählt wird wieder bewegen:

Maus-down / Text-Auswahl / Maus-Move-Out-Textbox / Maus-up

nur verwenden selectAll () auf ein und klicken Sie Ereignisse

private void textBox1_Enter(object sender, EventArgs e)
        {

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

Das finde ich am besten funktionieren, wenn Maustaste klicken und nicht sofort wieder loslassen:

    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;
    }

Meine Lösung ziemlich primitiv ist, funktioniert aber für meine Zwecke in Ordnung

private async void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
    if (sender is TextBox)
    {
        await Task.Delay(100);
        (sender as TextBox).SelectAll();
    }
}

Dies funktioniert für mich in .NET 2005 -

    ' * if the mouse button is down, do not run the select all.
    If MouseButtons = Windows.Forms.MouseButtons.Left Then
        Exit Sub
    End If

 ' * OTHERWISE INVOKE THE SELECT ALL AS DISCUSSED.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top