Cómo añadir un menú emergente que permita copiar al portapapeles de Windows el valor de una columna determinada, de la fila seleccionada actualmente, en un TListView. Se usará el IDE de programación Delphi y el lenguaje base Pascal.
Añadiremos al formulario el componente TListView (en la paleta de componentes Win32):
Y un componente de tipo TPopupMenu (en la paleta de componentes Standard):
Añadiremos las columnas que queramos al componente TListView, por ejemplo: ID, Usuario, Usuario a mostrar en impresora y Código destino:
Quedando:
Asociaremos el ListView con el PopupMenu, seleccionándolo en la propiedad PopupMenu del ListView:
El ListView se rellenará de datos (filas), usando un procedimiento Delphi. Como ejemplo, mostramos el código fuente Pascal (Delphi) que lee los usuarios de una tabla (tablaView), obtiene el nombre y los apellidos, los acorta para dejar 16 caracteres como máximo y rellena la lista anterior con los datos:
- ID: codigo del usuario.
- Usuario: nombre completo, compuesto por apellido primero, espacio, apellido segundo, coma, espacio y nombre.
- Usuario a mostrar en impresora: nombre corto (16 caracteres), acortando nombre y apellidos. Esto es útil para impresoras tipo Ricoh y pantallas de teléfono tipo Cisco, que admiten como máximo 16 caracteres.
- Codigo destino: un código identificativo.
Las columnas y datos anteriores son un ejemplo para rellenar el ListView, como es lógico, lo rellenaremos con los datos que necesitemos.
Puesto que, desde el formulario TformUsuario, estamos rellenando el ListView contenido en otro formulario (TformCSVEscaner), previamente tendremos que crear este formulario.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
procedure TformUsuario.actCSVEscanerExecute(Sender: TObject); var i : integer; RecIdx, ColIdx, numSeleccionados : integer; usrSel: array of Integer; ListItem : TListItem; codRegistro : integer; ident, nombre, apellido1, apellido2, nombreCorto : string; begin numSeleccionados := tablaView.Controller.SelectedRecordCount; //definimos el tamaño del array que contendrá //los usuarios seleccionados SetLength(usrSel, numSeleccionados); //recorremos cada usuario seleccionado para llenar el array for i := 0 to (numSeleccionados - 1) do begin RecIdx := tablaView.Controller.SelectedRecords[i].RecordIndex; ColIdx := tablaView.DataController.GetItemByFieldName('codigo').Index; usrSel[i] := tablaView.DataController.Values[RecIdx, ColIdx]; end; application.createform(TformCSVEscaner, formCSVEscaner); //rellenamos lista de usuarios en el formulario ricoh //Acortamos el nombre para mostrar (máximo 16 caracteres) for i := 0 to numSeleccionados - 1 do begin ListItem := formCSVEscaner.lsRicohUsuarios.Items.Add; codRegistro := usrSel[i]; ListItem.Caption := IntToStr(codRegistro); nombre := obtenerValor('nombreseparado', vtTablaUsuario, codRegistro); apellido1 := obtenerValor('apellido1', vtTablaUsuario, codRegistro); apellido2 := obtenerValor('apellido2', vtTablaUsuario, codRegistro); //Nombre completo ListItem.SubItems.Add(apellido1 + ' ' + apellido2 + ', ' + nombre); //Acortamos el nombre a 16 caracteres nombreCorto := nombre + ' ' + apellido1 + ' ' + apellido2; if Length(nombreCorto) > 16 then begin //Si tiene nombre muy largo (de más de 10 caracteres) lo cortamos if length(nombre) > 10 then nombre := copy(nombre, 0, 9); //Si los apellidos no suman más de 14 caracteres contando con el nombre los ponemos los dos //14 porque se cuentan los 2 espacios hasta 16 if (Length(nombre) + Length(apellido1) + Length(apellido2) <= 14) then nombreCorto := nombre + ' ' + apellido1 + ' ' + apellido2 else //Acortamos los apellidos begin nombreCorto := nombre + ' ' + copy(apellido1 + ' ' + apellido2, 0, 15 - length(nombre)); end; end; ListItem.SubItems.Add(nombreCorto); //Obtenemos del identificador los 5 últimos dígitos ident := obtenerValor('ident', vtTablaUsuario, codRegistro); if Length(ident) >= 5 then ident:= copy (ident, length(ident) - 4, 5); ListItem.SubItems.Add(ident); end; formCSVEscaner.ShowModal; end; |
Añadiremos los menús que necesitemos en el PopupMenu. En nuestro ejemplo, añadiremos tres menús:
- Copiar nombre para mostrar: copiará el contenido de la columna «Usuario a mostrar en impresora» al portapapeles, de la fila seleccionada.
- Copiar usuario: copiará el contenido de la columna «Usuario» al portapapeles, de la fila seleccionada.
- Copiar código destino: copiará el contenido de la columna «Código destino» al portapapeles, de la fila seleccionada.
Añadiremos ahora el código fuente para cada elemento del menú. Haciendo doble clic sobre el primero, añadiremos el siguiente código:
1 2 3 4 5 6 7 8 9 10 11 12 |
procedure TformCSVEscaner.mnuCopiarNombreMostrarClick(Sender: TObject); var texto : string; begin if lsRicohUsuarios.SelCount = 1 then begin texto := lsRicohUsuarios.Selected.SubItems.Strings[1]; Clipboard.AsText := texto; end else MessageDlg('No ha seleccionado ninguna fila.', mtInformation, [mbok],0); end; |
El código anterior, asignado al menú «Copiar nombre para mostrar», copiará al portapapeles de Windows el valor contenido en la columna 1 (que se corresponde con «Usuario a mostrar en impresora»), de la fila seleccionada actualmente.
Repetiremos el código para el resto de menús, cambiando el índice de la columna a copiar:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
procedure TformCSVEscaner.Copiarusuario1Click(Sender: TObject); var texto : string; begin if lsRicohUsuarios.SelCount = 1 then begin texto := lsRicohUsuarios.Selected.SubItems.Strings[0]; Clipboard.AsText := texto; end else MessageDlg('No ha seleccionado ninguna fila.', mtInformation, [mbok],0); end; procedure TformCSVEscaner.Copiarcdigodestino1Click(Sender: TObject); var texto : string; begin if lsRicohUsuarios.SelCount = 1 then begin texto := lsRicohUsuarios.Selected.SubItems.Strings[2]; Clipboard.AsText := texto; end else MessageDlg('No ha seleccionado ninguna fila.', mtInformation, [mbok],0); end; |
IMPORTANTE: para poder usar el procedimiento Clipboard, deberemos añadir al uses del formulario la unidad Clipbrd:
1 2 3 4 5 6 7 8 9 10 11 |
unit UnidadCSVEscaner; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, Buttons, Menus, Clipbrd; type TformCSVEscaner = class(TForm) dlGuardar: TSaveDialog; |
Ejecutando la aplicación, al pulsar con el botón derecho sobre una fila del ListView, nos mostrará el menú emergente, pulsando en una de sus opciones, copiará el texto de la columna correspondiente a la fila seleccionada al portapapeles de Windows: