Algunas acciones comunes con las cajas de textos |
Publicado el 27/Dic/2002
Actualizado el 03/Jun/2006
Algunas acciones comunes con las cajas de textos:
- Cambiar al siguiente control al pulsar Intro en una caja de textos (03/Jun/06)
- Seleccionar todo el código al recibir el foco (27/Dic/02)
- Evitar el pitido al pulsar Intro (y evitar que se interprete la tecla) (27/Dic/02)
- Cambiar una tecla pulsada por otra diferente (27/Dic/02)
- Seleccionar una parte del texto (27/Dic/02)
- Copiar el texto seleccionado en el ClipBoard (27/Dic/02)
- Cortar el texto seleccionado y dejarlo en el Clipboard (27/Dic/02)
- Pegar el texto del portapapeles (Clipboard) (27/Dic/02)
- Saber si se puede deshacer (27/Dic/02)
- Deshacer la última modificación (27/Dic/02)
(y código para VB6 usando API, para: Copiar, Cortar, Pegar y Seleccionar todo)
Cambiar al siguiente control al pulsar Intro en una caja de textos (03/Jun/06)
Como ya ocurría con VB6, podemos usar SendKeys para enviar una pulsación de la tecla TAB cuando detectemos que se ha pulsado la tecla Intro (o Enter).
Esa comprobación la haremos en el evento KeyPress de cada caja de textos, pero no es necesario que escribamos el mismo código en todas las cajas de textos en las que queramos esta funcionalidad, ya que en Visual Basic para .NET (y también en C#) se pueden asociar el mismo método o procedimiento para interceptar el evento de varios controles (siempre que sean compatibles los parámetros de esos eventos).Nota:
Lo que debes tener en cuenta es que esto lo que hará será "simular" la pulsación de la tecla TAB, por tanto si hay otros controles "en medio", el que recibirá el foco después de pulsar INTRO en esa caja de textos será el siguiente control que haya, no la siguiente caja de textos.
En VB6: Lo tendremos que hacer en cada una de las cajas de texto en la que queramos esa funcionalidad
If KeyAscii = vbKeyReturn Then KeyAscii = 0 SendKeys "{TAB}" End If
En VB.NET: Podemos asociar varios controles al mismo método de evento:
If e.KeyChar = ChrW(Keys.Enter) Then e.Handled = True SendKeys.Send("{TAB}") End If
En C#: Es como en VB, pero con punto y coma al final, je, je.
if( e.KeyChar == (char)Keys.Enter ) { e.Handled = true; SendKeys.Send("{TAB}"); }
Seleccionar todo el código al recibir el foco (27/Dic/02)
En Visual Basic clásico, cuando un TextBox recibe el foco, se suele usar algo como esto:
En el evento GotFocus del TextBox, hay que escribir:
Private Sub Text1_GotFocus() ' seleccionar el texto al recibir el foco With Text1 .SelStart = 0 .SelLength = Len(.Text) End With End Sub
En Visual Basic .NET es tan simple, que se hace con una sola instrucción:
Private Sub TextBox1_Enter(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles TextBox1.Enter ' seleccionar el texto al recibir el foco TextBox1.SelectAll() End Sub
En C# también se hace con una sola instrucción, pero al estilo C:
private void textBox1_Enter(object sender, System.EventArgs e) { textBox1.SelectAll(); }
Nota:
En Visual Studio .NET 2002 aunque existe el evento GotFocus, éste no se muestra en la lista de eventos disponibles, pero se puede usar el evento Enter, que si se muestra.
En la versión 2003, en VB se muestran los dos eventos, pero en C# sólo Enter.
De todas formas, te aclararé que primero se produce el evento Enter y después el GotFocus.
Según la documentación de VS .NET: Los eventos GotFocus y LostFocus son eventos de bajo nivel asociados a los mensajes de Windows WM_SETFOCUS y WM_KILLFOCUS. También recomienda que se usen los eventos Enter y Leave.
Evitar el pitido al pulsar Intro (y evitar que se interprete la tecla) (27/Dic/02)
En VB6, cuando interceptamos la tecla Intro, porque queramos hacer cualquier cosa cuando se pulsa en una caja de textos, solemos asignar un valor cero al parámetro recibido en el evento (KeyAscii), ese cero le indica al runtime que no tenga en cuenta la pulsación de la tecla.
Private Sub Text1_KeyPress(KeyAscii As Integer) ' si se pulsa Intro, asignar cero para ignorar la pulsación If KeyAscii = vbKeyReturn Then ' con esto hacemos que se ignore la pulsación KeyAscii = 0 '... el código ... ' (por ejemplo pasar a otro control) Text2.SetFocus End If End Sub
En VB.NET no existe el parámetro KeyAscii, en su lugar hay un parámetro de evento entre cuyos miembros está la propiedad KeyChar que representa a la tecla pulsada, pero esta propiedad es de solo lectura, por tanto no se puede asignar ningún valor. Pero, al menos para el caso que estamos tratando en este punto, eso no supone ningún inconveniente, ya que hay una propiedad que nos viene como anillo al dedo: Handled, si le asignamos un valor True a esta propiedad, la pulsación de la tecla será ignorada.
Private Sub TextBox1_KeyPress(ByVal sender As Object, _ ByVal e As System.Windows.Forms.KeyPressEventArgs) _ Handles TextBox1.KeyPress ' si la tecla pulsada es la tecla Intro If e.KeyChar = Convert.ToChar(Keys.Return) Then ' con esto hacemos que se ignore la pulsación e.Handled = True '... el código ... ' (por ejemplo pasar a otro control) TextBox2.Focus() End If End Sub
En C# sería como en VB.NET, pero tratando los caracteres al estilo C:
private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) { // si la tecla pulsada es la tecla Intro if (e.KeyChar == (char)13) { // con esto hacemos que se ignore la pulsación e.Handled = true; // ... el código ... // (por ejemplo pasar a otro control) textBox2.Focus(); } }
Cambiar una tecla pulsada por otra diferente (27/Dic/02)
En VB6: Como he mencionado antes, en VB.NET el parámetro que indica la tecla pulsada en el evento KeyPress, es de solo lectura, por tanto, algo que en VB6 es, (en esta ocasión), tan simple como esto:
Private Sub Text1_KeyPress(KeyAscii As Integer) ' cambiar el punto por la coma If KeyAscii = Asc(".") Then KeyAscii = Asc(",") End If End Sub
En VB.NET hay que utilizar SendKeys, algunos pensarán que es una mala opción, sobre todo si han tenido problemas en VB6 con SendKeys, la única "esperanza" que nos queda es pensar que ahora SendKeys funcionará bien (o mejor), ya que es una clase del .NET Framework, la cual también se puede usar con C#.
El código equivalente al mostrado anteriormente sería:Private Sub TextBox1_KeyPress(ByVal sender As Object, _ ByVal e As System.Windows.Forms.KeyPressEventArgs) _ Handles TextBox1.KeyPress ' cambiar el punto por la coma If e.KeyChar = "."c Then ' si no ignoramos esta pulsación, tendremos dos e.Handled = True ' enviar la nueva tecla SendKeys.Send(",") End If End SubTe aclaro un poco lo que se hace:
Para saber si es el punto, usamos "."c que sería el equivalente a Asc(".") es decir convertir un String en un Char.
El e.Handled = True es para evitar que se envíe la pulsación del punto al TextBox.
El SendKets.Send(",") envía la pulsación de la coma (o cualquier otra cadena) al control que tiene el foco.
En C# sería muy parecido a VB.NET (esto no lo voy a repetir más, ya que, salvo por la sintaxis del lenguaje, tanto en VB.NET como en C# se hace de la misma forma)
private void textBox1_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) { // cambiar el punto por la coma if (e.KeyChar == '.') { // si no ignoramos esta pulsación, tendremos dos e.Handled = true; // enviar la nueva tecla SendKeys.Send(","); } }
Seleccionar una parte del texto (27/Dic/02)
Este caso es muy parecido en ambas versiones de Visual Basic, ya que se utilizan las mismas instrucciones. Pero aún así, veamos el código en cada versión (y también en C#)
Para que el efecto sea visible, debemos asignar un valor False a la propiedad HideSelection del TextBox (en ambas versiones existe esa propiedad y lo que hace es que cuando el TextBox no tiene el foco se sigue mostrando la selección actual)
Con el siguiente código seleccionamos desde la 2ª posición, 3 caracteres. Si el contenido del TextBox fuese TextBox1, se seleccionaría ext.En VB6:
Private Sub seleccionarCmd_Click() Text1.SelStart = 1 ' realmente es la 2ª posición Text1.SelLength = 3 ' seleccionamos tres caracteres End Sub
En VB.NET:
Private Sub seleccionarBtn_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles seleccionarBtn.Click TextBox1.SelectionStart = 1 ' realmente es la 2ª posición TextBox1.SelectionLength = 3 ' seleccionamos 3 caracteres End Sub
En C#:
private void seleccionarBtn_Click(object sender, System.EventArgs e) { textBox1.SelectionStart = 1; // realmente es la 2ª posición textBox1.SelectionLength = 3; // seleccionamos 3 caracteres }
Copiar el texto seleccionado en el ClipBoard (27/Dic/02)
Para copiar texto de un TextBox en el portapapeles, en VB6 tenemos que usar el objeto Clipboard para realizar esa acción (o usar el API de Windows), en .NET las cajas de textos tienen un método que permite realizar esa acción sin necesidad de usar el portapapeles.
En estos ejemplos, si hay texto seleccionado, se copiará sólo la selección, si no hay selección previa, se copiará todo el contenido.
En VB6:
Private Sub copiarCmd_Click() ' copiar la selección en el Clipboard If Text1.SelLength > 0 Then Clipboard.SetText Text1.SelText Else ' copiar todo el texto Clipboard.SetText Text1.Text End If End Sub
En VB.NET:
Private Sub copiarBtn_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles copiarBtn.Click If TextBox1.SelectionLength = 0 Then ' en .NET copia la selección actual ' por tanto, si no hay selección, lo seleccionamos todo TextBox1.SelectAll() End If ' copiamos la selección en el portapapeles TextBox1.Copy() End Sub
En C#:
private void copiarBtn_Click(object sender, System.EventArgs e) { if (textBox1.SelectionLength == 0) { // en .NET copia la selección actual // por tanto, si no hay selección, lo seleccionamos todo textBox1.SelectAll(); } // copiamos la selección en el portapapeles textBox1.Copy(); }
Cortar el texto seleccionado (y dejarlo en el ClipBoard) (27/Dic/02)
La operación de cortar es la misma que la de copiar, además de eliminar el texto.
En VB6, nuevamente, tenemos que usar el objeto Clipboard, en .NET también existe un método para realizar esa operación.En estos ejemplos, sólo se cortará si hay texto seleccionado.
En VB6:
Private Sub cortarCmd_Click() ' copiar la selección en el Clipboard If Text1.SelLength > 0 Then Clipboard.SetText Text1.SelText ' eliminar la selección Text1.SelText = "" End If End Sub
En VB.NET:
Private Sub cortarBtn_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles cortarBtn.Click ' si hay texto seleccionado If TextBox1.SelectionLength > 0 Then ' cortarlo TextBox1.Cut() End If End Sub
En C#:
private void cortarBtn_Click(object sender, System.EventArgs e) { // si hay texto seleccionado if (textBox1.SelectionLength > 0) { // cortarlo textBox1.Cut(); } }
Pegar el texto del portapapeles (Clipboard) (27/Dic/02)
Al igual que ocurría con la copia de texto en el portapapeles, para pegar del portapapeles al TextBox en .NET se puede hacer con un llamada al método Paste, mientras que con VB6, hay que seguir usando el objeto Clipboard.
En estos ejemplos, si hay texto seleccionado, se sustituirá por lo que haya en el portapapeles, sino, se pegará sustituyendo todo el texto.
En VB6:
Private Sub pegarCmd_Click() ' pegar en el textbox lo que haya en el clipboard ' si hay alguna selección sustituirlo If Text1.SelLength > 0 Then Text1.SelText = Clipboard.GetText Else Text1.Text = Clipboard.GetText End If End Sub
En VB.NET:
Private Sub PegarBtn_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles PegarBtn.Click ' pegar en el textbox lo que haya en el clipboard ' si hay alguna selección sustituirlo If TextBox1.SelectionLength = 0 Then ' si no hay selección, se sustituirá lo que había TextBox1.SelectAll() End If TextBox1.Paste() End Sub
En C#:
private void PegarBtn_Click(object sender, System.EventArgs e) { // pegar en el textbox lo que haya en el clipboard // si hay alguna selección sustituirlo if (textBox1.SelectionLength == 0) { // si no hay selección, se sustituirá lo que había textBox1.SelectAll(); } textBox1.Paste(); }
Saber si se puede deshacer (27/Dic/02)
En VB6, para saber si se puede deshacer lo escrito en un TextBox, hay que utilizar el API de Windows, sin embargo en .NET simplemente se pregunta a una propiedad que ahora incluyen las cajas de texto y se sabe si se puede o no deshacer.
En VB6:
Para saber si se puede deshacer, hay que usar la función SendMessage del API de Windows, la declaración sería la siguiente, esta declaración hay que ponerla en la parte de declaraciones (General) del formulario.Private Declare Function SendMessage Lib "User32" Alias "SendMessageA" _ (ByVal hWnd As Long, ByVal wMsg As Long, _ ByVal wParam As Long, ByVal lParam As Long) As Long
Private Sub canUndoCmd_Click() ' saber si se puede deshacer Const EM_CANUNDO As Long = &HC6 ' If SendMessage(Text1.hWnd, EM_CANUNDO, 0&, 0&) Then Label1 = "Se puede deshacer" Else Label1 = "NO se puede deshacer" End If End Sub
En VB.NET:
Private Sub canUndoBtn_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles canUndoBtn.Click If TextBox1.CanUndo Then Label1.Text = "Se puede deshacer" Else Label1.Text = "NO se puede deshacer" End If End Sub
En C#:
private void canUndoBtn_Click(object sender, System.EventArgs e) { if (textBox1.CanUndo) { label1.Text = "Se puede deshacer"; } else { label1.Text = "NO se puede deshacer"; } }
Deshacer la última modificación (27/Dic/02)
Para poder deshacer los últimos cambios realizados en un TextBox, con VB6 hay que usar el API de Windows, pero con .NET simplemente se llama a un método.
En VB6:
La función del API usada para la operación deshacer es la misma que la mostrada en el punto anterior.El problema con VB6 es que para poder deshacer, hay que utilizar también el API de Windows para realizar las acciones de cortar y borrar, si no se hace así, no podremos deshacer.
Aquí te muestro las operaciones de Copiar, Cortar, Pegar y Seleccionar todo usando el API de Windows. Si usas el API no deberías usar el método normal, ya que no son compatibles.
Copiar usando API
' copiar lo seleccionado, usando el API Const WM_COPY As Long = &H301 Const EM_SETSEL As Long = &HB1 ' ' si no hay selección, seleccionarlo todo If Text1.SelLength = 0 Then SendMessage Text1.hWnd, EM_SETSEL, 0&, -1& End If SendMessage Text1.hWnd, WM_COPY, 0&, 0&
Cortar usando API
' cortar el texto seleccionado, usando API ' sólo, si hay algo seleccionado... Const WM_CUT As Long = &H300 SendMessage Text1.hWnd, WM_CUT, 0&, 0&
Pegar usando API
' pegar usando el API Const WM_PASTE As Long = &H302 ' SendMessage Text1.hWnd, WM_PASTE, 0&, 0&
Seleccionar todo usando API
Const EM_SETSEL As Long = &HB1 ' ' seleccionarlo todo SendMessage Text1.hWnd, EM_SETSEL, 0&, -1&
Deshacer
Private Sub deshacerCmd_Click() Const EM_CANUNDO As Long = &HC6 Const EM_UNDO As Long = &HC7 ' ' se comprueba si se puede deshacer If SendMessage(Text1.hWnd, EM_CANUNDO, 0&, 0&) Then ' si es así, se deshace SendMessage Text1.hWnd, EM_UNDO, 0&, 0& End If End Sub
En VB.NET:
Private Sub deshacerBtn_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles deshacerBtn.Click ' si se puede deshacer If TextBox1.CanUndo Then ' deshacer TextBox1.Undo() End If End Sub
En C#:
private void deshacerBtn_Click(object sender, System.EventArgs e) { // si se puede deshacer if (textBox1.CanUndo) { // deshacer textBox1.Undo(); } }