Hacer que un WinForms TextBox se comporte como la barra de direcciones de su navegador

Cuando un cuadro de texto de Win # de C # recibe el foco, quiero que se comporte como la barra de direcciones de su navegador.

Para ver lo que quiero decir, haz clic en la barra de direcciones de tu navegador web. Notarás el siguiente comportamiento:

  1. Hacer clic en el cuadro de texto debería seleccionar todo el texto si el cuadro de texto no estaba enfocado previamente.
  2. Deslice el mouse hacia abajo y arrastre en el cuadro de texto para seleccionar solo el texto que he resaltado con el mouse.
  3. Si el cuadro de texto ya está enfocado, al hacer clic no se selecciona todo el texto.
  4. Enfocar el cuadro de texto mediante progtwigción o mediante la tabulación del teclado debe seleccionar todo el texto.

Quiero hacer exactamente esto en WinForms.

LA ALERTA DE PISTOLAS MÁS RÁPIDA: ¡por favor lea lo siguiente antes de responder! Gracias chicos. 🙂

Llamar a .SelectAll () durante los eventos .Enter o .GotFocus no funcionará porque si el usuario hizo clic en el cuadro de texto, el símbolo de intercalación se colocará donde hizo clic, anulando así la selección de todo el texto.

Llamar a .SelectAll () durante el evento .Click no funcionará porque el usuario no podrá seleccionar ningún texto con el mouse; la llamada .SelectAll () seguirá sobrescribiendo la selección de texto del usuario.

Llamar a BeginInvoke (cuadro de texto (Acción ).SelectAll) en el evento focus / enter. Enter no funciona porque rompe la regla # 2 anterior, seguirá anulando la selección del usuario en el foco.

Antes que nada, ¡gracias por las respuestas! 9 respuestas totales. Gracias.

Malas noticias: todas las respuestas tenían algunas peculiaridades o no funcionaban del todo bien (o no funcionaban). He agregado un comentario a cada una de tus publicaciones.

Buenas noticias: he encontrado la manera de hacerlo funcionar. Esta solución es bastante sencilla y parece funcionar en todos los escenarios (desplazarse hacia abajo, seleccionar texto, tabular el foco, 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(); } } 

Hasta donde puedo decir, esto hace que un cuadro de texto se comporte exactamente como la barra de direcciones de un navegador web.

Espero que esto ayude al próximo tipo que intenta resolver este problema engañosamente simple.

Gracias de nuevo, muchachos, por todas sus respuestas que me ayudaron a seguir el camino correcto.

Encontré una solución más simple para esto. Implica iniciar SelectAll de forma asincrónica utilizando Control.BeginInvoke para que se produzca después de que se hayan producido los eventos Enter y 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(); }); } 

En VB.NET (gracias a Krishanu Dey )

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

Su solución es buena, pero falla en un caso específico. Si le da al foco de TextBox seleccionando un rango de texto en lugar de simplemente hacer clic, el indicador de alreadyFocussed no se establece en verdadero, por lo que cuando hace clic en el TextBox por segunda vez, todo el texto se selecciona.

Aquí está mi versión de la solución. También puse el código en una clase que hereda TextBox, por lo que la lógica está muy bien escondida.

 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 un poco tonto, pero en su evento de clic, use SendKeys.Send( "{HOME}+{END}" ); .

Haga clic en evento de cuadro de texto? O incluso el evento MouseCaptureChanged funciona para mí. – OKAY. no funciona

Entonces tienes que hacer 2 cosas:

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

También funciona para tabular (a través de cuadros de texto): llama a SelectAll () en Entrar solo por si acaso …

Una respuesta de una línea que uso … es posible que te estés pateando a ti mismo …

En el evento Enter:

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

 'Inside the Enter event TextBox1.SelectAll(); 

Ok, después de probarlo aquí es lo que quieres:

  • En el evento Enter, inicie una bandera que indique que ha estado en el evento enter
  • En el evento Click, si configura el indicador, llame a .SelectAll () y reinicie el indicador.
  • En el evento MouseMove, establezca el indicador ingresado en falso, lo que le permitirá hacer clic en resaltar sin tener que ingresar primero al cuadro de texto.

Esto seleccionó todo el texto en la entrada, pero me permitió resaltar parte del texto después, o permitirle resaltar en el primer clic.

Por solicitud:

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

Para mí, la tabulación en el control selecciona todo el texto.

Aquí hay una función de ayuda que lleva la solución al siguiente nivel: reutilización sin herencia.

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

Para usar esto simplemente llame a la función que pasa un TextBox y se ocupará de todas las partes desordenadas para usted. Sugiero conectar todos sus cuadros de texto en el evento Form_Load. Puede colocar esta función en su forma, o si le gusto, en algún lugar de una clase de utilidad para una reutilización aún mayor.

Esto es similar a la respuesta popular de nzhenry, pero me resulta más fácil no tener que subclase:

  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 

Esto funcionó para 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; } 

SelectAll nunca funcionó para mí.

Esto funciona.

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

Encontré una solución aún más simple:

Para asegurarse de que todo el texto esté seleccionado al hacer clic en un cuadro de texto, asegúrese de que el controlador de clic llame al controlador de entrada. ¡No hay necesidad de variables adicionales!

Ejemplo:

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

Curiosamente, un ComboBox con DropDownStyle = Simple tiene exactamente el comportamiento que estás buscando, creo.

(Si reduce la altura del control para que no se muestre en la lista, y luego en un par de píxeles más, no hay una diferencia efectiva entre el ComboBox y el TextBox).

¿Por qué no simplemente usas el MouseDown-Event del cuadro de texto? Funciona bien para mí y no necesita un booleano adicional. Muy limpio y simple, por ejemplo .:

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

Llamé a SelectAll dentro del evento MouseUp y funcionó bien para mí.

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

Solo obtenga una clase de TextBox o MaskedTextBox:

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

Y úsalo en tus formularios.

¿Has probado la solución sugerida en el foro de MSDN “Windows Forms General” que simplemente subclasifica TextBox?

En realidad, GotFocus es el evento correcto (mensaje realmente) en el que estás interesado, ya que no importa cómo llegues al control, lo conseguirás incluso con el tiempo. La pregunta es cuándo llamas a SelectAll ().

Prueba esto:

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

Para un grupo de cuadros de texto en un formulario:

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

El siguiente parece funcionar. El evento enter maneja la tabulación al control y MouseDown funciona cuando se hace clic en el control.

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

Sé que esto ya estaba resuelto, pero tengo una sugerencia que creo que es bastante simple.

En el evento de mouse todo lo que tienes que hacer es colocar

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

Parece que funciona en VB.NET (sé que esta es una pregunta de C # … lamentablemente me veo obligado a usar VB en mi trabajo … y estaba teniendo este problema, que es lo que me trajo aquí … )

No he encontrado ningún problema aún … excepto por el hecho de que no selecciona de inmediato al hacer clic, pero estaba teniendo problemas con eso …

La siguiente solución funciona para mí. OnKeyDown OnKeyUp evento OnKeyDown y OnKeyUp para mantener el texto del cuadro de texto siempre seleccionado.

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

Establezca la selección cuando abandone el control. Estará allí cuando regrese. Tab alrededor del formulario y cuando regrese al control, se seleccionará todo el texto.

Si ingresa con el mouse, el cursor se colocará correctamente en el punto donde hizo clic.

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

La respuesta puede ser bastante más simple que TODAS las anteriores, por ejemplo (en WPF):

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

por supuesto, no puedo saber cómo quiere usar este código, pero la parte principal que debe ver aquí es: Primera llamada .Focus () y luego llamada .SelectAll ();

Solución muy 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; } } 

EDITAR: Original OP estaba particularmente preocupado por la secuencia de mouse / down / text-selection / mouse-up, en cuyo caso la solución simple anterior terminaría con el texto parcialmente seleccionado.

Esto debería resolver * el problema (en la práctica, yo intercepto 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 realidad, la siguiente secuencia termina con la selección de texto parcial, pero luego, si mueve el mouse sobre el cuadro de texto, todo el texto se seleccionará nuevamente:

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

solo use selectall () al ingresar y hacer clic en eventos

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

Encuentro que esto funciona mejor, cuando el mouse hace clic y no se lanza inmediatamente:

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

Mi solución es bastante primitiva pero funciona bien para mi propósito

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

Esto está funcionando para mí en .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.