
Cómo agregar elementos dinámicamente a un menú de TPopUp en Delphi
Cuando se trabaja con menús o menús PopUp en aplicaciones Delphi, en la mayoría de los escenarios, se crean los elementos de menú en tiempo de diseño. Cada elemento del menú está representado por una clase TMenuItem Delphi. Cuando un usuario selecciona (hace clic) en un elemento, el evento OnClick se dispara para que usted (como desarrollador) tome el evento y responda a él.
Puede haber situaciones en las que los elementos del menú no se conozcan en tiempo de diseño, pero necesiten ser añadidos en tiempo de ejecución (instanciados dinámicamente).
Agregar TMenuItem en tiempo de ejecución
Supongamos que hay un componente de TPopupMenu llamado "PopupMenu1" en un formulario Delphi, para agregar un elemento al menú emergente se puede escribir un fragmento de código como:
var
menuItem : TMenuItem;
begin
menuItem := TMenuItem.Create(PopupMenu1) ;
menuItem.Caption := 'Item added at ' + TimeToStr(now) ;
menuItem.OnClick := PopupItemClick;
//assign it a custom integer value..
menuItem.Tag := GetTickCount;
PopupMenu1.Items.Add(menuItem) ;
end;
Notas:
- En el código anterior, se añade un elemento al componente PopupMenu1. Tenga en cuenta que asignamos un valor entero a la propiedad Tag. La propiedad Tag (cada componente de Delphi la tiene) está diseñada para permitir a un desarrollador asignar un valor entero arbitrario almacenado como parte del componente.
- La función de la API GetTickCount recupera el número de milisegundos que han transcurrido desde que se inició Windows.
- Para el manejador de eventos OnClick, asignamos "PopupItemClick" - el nombre de la función con la firma *correcta*.
Importante: al hacer clic en el elemento añadido dinámicamente, se ejecutará el "PopupItemClick". Para diferenciar entre uno o más elementos añadidos en tiempo de ejecución (todos ejecutando el código en PopupItemClick) podemos utilizar el parámetro Sender:
procedure TMenuTestForm.PopupItemClick(Sender: TObject) ;
var
menuItem : TMenuItem;
begin
if NOT (Sender is TMenuItem) then
begin
ShowMessage('Hm, if this was not called by Menu Click, who called this?!') ;
ShowMessage(Sender.ClassName) ;
exit;
end;
menuItem := TMenuItem(sender) ;
ShowMessage(Format('Clicked on "%s", TAG value: %d',[menuItem.Name, menuItem.Tag])) ;
end;
El método "PopupItemClick" comprueba primero si el remitente es realmente un objeto TMenuItem. Si el método se ejecuta como resultado de un elemento de menú, el manejador de eventos OnClick simplemente muestra un mensaje de diálogo con el valor Tag que se asignó cuando el elemento de menú se añadió al menú.
¿Cadena personalizada en (creada en tiempo de ejecución) TMenuItem?
En aplicaciones del mundo real, usted podría necesitar más flexibilidad. Supongamos que cada elemento "representará" una página web - un valor de cadena sería necesario para mantener la URL de la página web. Cuando el usuario selecciona este elemento, puede abrir el navegador web predeterminado y navegar hasta la URL asignada con el elemento de menú.
Aquí hay una clase TMenuItemExtended personalizada equipada con una propiedad "Value" de cadena personalizada:
type
TMenuItemExtended = class(TMenuItem)
private
fValue: string;
published
property Value : string read fValue write fValue;
end;
A continuación, se explica cómo añadir este elemento de menú "extendido" a un PoupMenu1:
var
menuItemEx : TMenuItemExtended;
begin
menuItemEx := TMenuItemExtended.Create(PopupMenu1) ;
menuItemEx.Caption := 'Extended added at ' + TimeToStr(now) ;
menuItemEx.OnClick := PopupItemClick;
//assign it a custom integer value..
menuItemEx.Tag := GetTickCount;
//this one can even hold a string value
menuItemEx.Value := 'http://delphi.about.com';
PopupMenu1.Items.Add(menuItemEx) ;
end;
Ahora, el "PopupItemClick" debe ser modificado para procesar correctamente este elemento de menú:
procedure TMenuTestForm.PopupItemClick(Sender: TObject) ;
var
menuItem : TMenuItem;
begin
//...same as above
if sender is TMenuItemExtended then
begin
ShowMessage(Format('Ohoho Extended item .. here''s the string value : %s',[TMenuItemExtended(Sender).Value])) ;
end;
end;
Nota: para abrir el explorador web predeterminado, puede utilizar la propiedad Value como parámetro de una función de la API de ShellExecuteEx.
Eso es todo. Depende de usted extender el TMenuItemExtended según sus necesidades. La sección Crear componentes Delphi personalizados es donde buscar ayuda para crear sus propias clases/componentes.