Operaciones sobre selecciones de texto

El usuario puede seleccionar una parte del texto incluido en un control edit, bien usando el ratón (que será lo más frecuente), o bien mediente el teclado, (manteniendo pulsada la tecla de mayúsculas y desplazando el cursor mediante el las teclas de movimiento del cursor).

Estamos acostumbrados ya a las operaciones frecuentes que se pueden hacer sobre una selección: copiar, cortar, borrar o pegar. Veamos ahora cómo podemos realizar estas operaciones en nuestros controles edit.

Cualquier control edit procesará los mensajes WM_CUT, WM_COPY, WM_CLEAR y WM_PASTE que reciba.

En el caso del mensaje WM_CUT, se copiará el texto seleccionado en el portapapeles y después se eliminará.

En el caso del mensaje WM_COPY, el texto seleccionado se copiará en el portapapeles.

En el caso del mensaje WM_CLEAR, el texto seleccionado se eliminará, sin copiarse en el portapapeles.

Y en el caso del mensaje WM_PASTE, el texto que esté en el portapapeles se copiará en la posición actual del caret en el control edit o sustituyendo al texto seleccionado, si existe.

Estas acciones están ya implementadas en el procedimiento de ventana de la clase "EDIT", por lo que bastará con enviar cualquiera de estos mensajes a un control para que funcionen.

Es más, las versiones actuales de Windows desplegarán un menú contextual al pulsar el botón derecho del ratón sobre cualquier control edit. Ese menú contendrá estos cuatro comandos: cortar, copiar, pegar y eliminar, y otros dos: deshacer y seleccionar todo.

También funcionan, cuando el control edit tiene el foco, las combinaciones de teclas para estas seis acciones: [control]+x para cortar, [control]+c para copiar, [control]+v para pegar y [supr] para borrar y [control]+z para deshacer.

Por nuestra parte, podemos añadir estos mensajes a nuestros menús, y enviarlos al control edit que tenga el foco en el momento en que se seleccionen.

Además, disponemos de otros mensajes para controlar la selección de texto.

El mensaje EM_GETSEL nos sirve para obtener los índices de los caracteres correspondientes al inicio y final de la selección actual. Más concretamente, obtendremos el índice del primer carácter de la selección y el del primero no seleccionado a continuación de la selección. Por ejemplo, si la selección incluye los caracteres 10º al 15º de texto de un control, obtendremos los valores 9 y 15:

Texto de ejemplo para ilustrar la selección.
00000000001111111111222222222233333333334444
01234567890123456789012345678901234567890123
   int inicio, final;
   
   SendMessage(hctrl, EM_GETSEL, (WPARAM)&inicio, (LPARAM)&final);
   sprintf(mensaje, "Selección actual de %d a %d", inicio, final);
   MessageBox(hwnd, mensaje, "Ejemplo de control edit", MB_OK);

De forma simétrica, podemos seleccionar una parte del texto mediante el mensaje EM_SETSEL. Si seleccionamos una parte del texto que no es visible en pantalla, Windows no lo mostrará de forma automática, y el caret quedará fuera de la parte visible del control. Si queremos que el caret sea visble debemos usar el mensaje EM_SCROLLCARET:

   SendMessage(hctrl, EM_SETSEL, 1500, 1554);
   SendMessage(hctrl, EM_SCROLLCARET, 0, 0);

Por último, el mensaje EM_REPLACESEL nos permite sustituir el texto actualmente seleccionado por otro:

   char nuevotexto[64];
   
   strcpy(nuevotexto, "TEXTO SUSTITUIDO");
   SendMessage(hctrl, EM_REPLACESEL, TRUE, (LPARAM)nuevotexto);

El parámetro wParam de este mensaje es un valor booleano que indica si la operación de sustitución puede ser deshecha o no. TRUE significa que se podrá deshacer, FALSE que no.

Selecciones siempre visibles

Por defecto, si no indicamos lo contrario, el texto seleccionado en un control edit, permanecerá resaltado sólo mientras el control tiene el foco del teclado. Sin embargo, si creamos el control con el estilo ES_NOHIDESEL, el resaltado permanece aunque el control pierda el foco.

Deshacer cambios (undo)

Otra tarea que realiza Windows con los controles edit es la de deshacer cambios, aunque el soporte para esta tarea es limitado, ya que sólo es posible deshacer el último cambio realizado en un control edit.

Al igual que sucede con los mensaje WM_CUT, WM_COPY, WM_PASTE y WM_CLEAR, el mensaje EM_UNDO se procesa de forma automática por el procedimiento de ventana del control edit. Por lo tanto bastará con enviar este mensaje a un control edit, y si es posible, se deshará el último cambio realizado.

SendMessage(hctrl, EM_UNDO, 0, 0);

Disponemos de otros dos mensajes relacionados con estas operaciones. El mensaje EM_CANUNDO nos permite averiguar si es posible deshacer alguna operación de edición. Es decir, si al enviar el mensaje EM_UNDO se deshará algún cambio.

Por último, el mensaje EM_EMPTYUNDOBUFFER vacía el buffer de deshacer, es decir, anula la posibilidad de deshacer cualquier operación de edición.

Para los controles edit sólo se almacena una operación de deshacer, es decir, que enviar repetidamente el mensaje EM_UNDO sólo deshará la última operación de edición, no las anteriores. Si lo último que se hizo fue eliminar un fragmento de texto, el primer mensaje EM_UNDO restaurará el texto eliminado, el segundo volverá a eliminarlo, el tercero lo restaurará de nuevo, y así sucesivamente.

Para operaciones de deshacer más elaboradas deberemos programar nosotros mismos las rutinas necesarias.