Faire un TextFox WinForms se comporter comme la barre d’adresse de votre navigateur

Lorsqu’une zone de texte C # WinForms reçoit le focus, je veux qu’elle se comporte comme la barre d’adresse de votre navigateur.

Pour voir ce que je veux dire, cliquez dans la barre d’adresse de votre navigateur Web. Vous remarquerez le comportement suivant:

  1. En cliquant dans la zone de texte, vous devez sélectionner tout le texte si la zone de texte n’a pas été précédemment ciblée.
  2. Faites glisser la souris dans la zone de texte et sélectionnez uniquement le texte surligné avec la souris.
  3. Si la zone de texte est déjà ciblée, le fait de cliquer ne sélectionne pas tout le texte.
  4. Focaliser la zone de texte par programmation ou par tabulation du clavier devrait sélectionner tout le texte.

Je veux faire exactement cela dans WinForms.

ALERTE DE PISTOLET LE PLUS RAPIDE: veuillez lire ce qui suit avant de répondre! Merci les gars. 🙂

L’appel de .SelectAll () pendant les événements .Enter ou .GotFocus ne fonctionnera pas car si l’utilisateur a cliqué sur la zone de texte, le curseur sera placé là où il a cliqué, désélectionnant ainsi tout le texte.

L’appel de .SelectAll () pendant l’événement .Click ne fonctionnera pas car l’utilisateur ne pourra sélectionner aucun texte avec la souris. l’appel .SelectAll () continuera à écraser la sélection de texte de l’utilisateur.

L’appel de BeginInvoke ((Action) textbox.SelectAll) à l’événement focus / enter enter ne fonctionne pas car il enfreint la règle n ° 2 ci-dessus, il continuera à remplacer la sélection de l’utilisateur à la focalisation.

    Tout d’abord, merci pour les réponses! 9 réponses au total. Je vous remercie.

    Mauvaise nouvelle: toutes les réponses avaient quelques bizarreries ou ne fonctionnaient pas correctement (ou pas du tout). J’ai ajouté un commentaire à chacun de vos messages.

    Bonne nouvelle: j’ai trouvé un moyen de le faire fonctionner. Cette solution est assez simple et semble fonctionner dans tous les scénarios (mise en sourdine, sélection de texte, ciblage par tabulation, etc.)

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

    Autant que je sache, cela provoque un comportement de la zone de texte exactement comme la barre d’adresse d’un navigateur Web.

    J’espère que cela aidera le prochain gars qui essaie de résoudre ce problème si simple.

    Merci encore, les gars, pour toutes vos réponses qui m’ont aidé à suivre le bon chemin.

    J’ai trouvé une solution plus simple à cela. Cela implique de lancer le SelectAll de manière asynchrone en utilisant Control.BeginInvoke pour qu’il se produise après que les événements Enter et Click se soient produits:

    En C #:

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

    Dans VB.NET (merci à Krishanu Dey )

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

    Votre solution est bonne, mais échoue dans un cas spécifique. Si vous donnez le focus TextBox en sélectionnant une plage de texte au lieu de simplement cliquer, l’indicateur alreadyFocussed n’est pas défini sur true. Ainsi, lorsque vous cliquez dans la TextBox une seconde fois, tout le texte est sélectionné.

    Voici ma version de la solution. J’ai aussi mis le code dans une classe qui hérite de TextBox, donc la logique est bien cachée.

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

    C’est un peu kludgey, mais dans votre événement click, utilisez SendKeys.Send( "{HOME}+{END}" ); .

    Cliquez sur l’événement de la zone de texte? Ou même l’événement MouseCaptureChanged fonctionne pour moi. – D’ACCORD. ne fonctionne pas

    Donc, vous devez faire 2 choses:

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

    Fonctionne également pour la tabulation (via textBoxes) – appelez SelectAll () dans Enter au cas où …

    Une réponse en une ligne que j’utilise

    Dans l’événement Enter:

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

     'Inside the Enter event TextBox1.SelectAll(); 

    Ok, après l’avoir essayé, voici ce que vous voulez:

    • Sur l’événement Enter, commencez un drapeau indiquant que vous avez participé à l’événement enter.
    • Sur l’événement Click, si vous définissez l’indicateur, appelez .SelectAll () et réinitialisez l’indicateur.
    • Sur l’événement MouseMove, définissez l’indicateur saisi sur false, ce qui vous permet de cliquer sur le bouton Mettre en évidence sans avoir à entrer dans la zone de texte en premier.

    Cela a sélectionné tout le texte sur l’entrée, mais m’a permis de mettre en évidence une partie du texte par la suite, ou vous permettre de mettre en évidence sur le premier clic.

    Sur demande:

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

    Pour moi, la tabulation dans le contrôle sélectionne tout le texte.

    Voici une fonction d’assistance qui amène la solution au niveau supérieur – réutilisation sans inheritance.

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

    Pour l’utiliser, appelez simplement la fonction en passant une TextBox et elle s’occupe de tous les bits en désordre pour vous. Je suggère de câbler toutes vos zones de texte dans l’événement Form_Load. Vous pouvez placer cette fonction dans votre formulaire ou, si vous le souhaitez, dans une classe d’utilitaires pour une réutilisation encore plus poussée.

    Ceci est similaire à la réponse populaire de nzhenry, mais je trouve plus facile de ne pas avoir à sous-classer:

      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 

    Cela a fonctionné pour un TextBox WPF / XAML.

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

    SelectAll n’a jamais fonctionné pour moi.

    Cela marche.

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

    J’ai trouvé une solution encore plus simple:

    Pour vous assurer que tout le texte est sélectionné en cliquant sur une zone de texte, assurez-vous que le gestionnaire de clics appelle le gestionnaire de saisie. Pas besoin de variables supplémentaires!

    Exemple:

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

    Fait intéressant, un ComboBox avec DropDownStyle = Simple a à peu près exactement le comportement que vous recherchez, je pense.

    (Si vous réduisez la hauteur du contrôle pour ne pas afficher la liste – et ensuite de quelques pixels de plus – il n’y a pas de différence efficace entre la zone de liste déroulante et la zone de texte.)

    Pourquoi n’utilisez-vous pas simplement l’événement MouseDown de la zone de texte? Cela fonctionne bien pour moi et n’a pas besoin d’un booléen supplémentaire. Très propre et simple, par ex .:

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

    J’ai appelé SelectAll dans l’événement MouseUp et cela a bien fonctionné pour moi.

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

    Dérivez une classe de TextBox ou MaskedTextBox:

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

    Et utilisez-le sur vos formulaires.

    Avez-vous essayé la solution proposée sur le forum MSDN “Windows Forms General” qui sous-classe simplement TextBox?

    En fait, GotFocus est le bon événement (message vraiment) qui vous intéresse, car peu importe comment vous obtenez le contrôle, vous l’obtiendrez même éventuellement. La question est de savoir quand vous appelez SelectAll ().

    Essaye ça:

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

    Pour un groupe de zones de texte dans un formulaire:

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

    Le ci-dessous semble fonctionner. L’événement enter gère la tabulation du contrôle et le MouseDown fonctionne lorsque l’utilisateur clique sur le contrôle.

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

    Je sais que cela a déjà été résolu mais j’ai une suggestion qui, à mon avis, est plutôt simple.

    Dans la souris, tout ce que vous avez à faire est de placer

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

    Cela semble fonctionner pour moi dans VB.NET (je sais que c’est une question C # … malheureusement, je suis obligé d’utiliser VB à mon travail .. et j’avais ce problème, ce qui m’a amené ici … )

    Je n’ai pas encore trouvé de problème avec elle, sauf que le fait de ne pas sélectionner immédiatement le clic, mais j’avais des problèmes avec ça …

    La solution suivante fonctionne pour moi. J’ai ajouté le remplacement d’événement OnKeyDown et OnKeyUp pour conserver le texte TextBox toujours sélectionné.

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

    Définissez la sélection lorsque vous quittez le contrôle. Il sera là quand vous reviendrez. Tab autour du formulaire et lorsque vous revenez au contrôle, tout le texte sera sélectionné.

    Si vous entrez par la souris, le curseur sera placé à l’endroit où vous avez cliqué.

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

    La réponse peut être en fait plus simple que TOUS les points ci-dessus, par exemple (dans WPF):

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

    Bien sûr, je ne peux pas savoir comment vous voulez utiliser ce code, mais la partie principale à examiner ici est la suivante: appelez d’abord .Focus (), puis appelez .SelectAll ();

    Solution très simple:

      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: L’OP original était particulièrement concerné par la séquence de sélection de la souris / du texte / de la souris, auquel cas la solution simple ci-dessus aboutirait à une sélection partielle du texte.

    Cela devrait résoudre * le problème (en pratique, j’intercepte 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 ); } 

    * En fait, la séquence suivante se termine par une sélection partielle du texte, mais si vous déplacez la souris sur la zone de texte, tout le texte sera à nouveau sélectionné:

    bas de la souris / sélection de texte / déplacement de la souris

    il suffit d’utiliser selectall () sur les événements enter et click

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

    Je trouve que cela fonctionne mieux, lorsque la souris clique et ne lâche pas immédiatement:

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

    Ma solution est assez primitive mais fonctionne bien pour mon but

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

    Cela fonctionne pour moi dans .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.