PDA

Ver la Versión Completa : OnClick dinamicamente


barakuda
24-06-2018, 19:36:15
Hola a tod@.

Verán hace tiempo hice un programa donde utilizaba la propiedad OnClick de los TImages de las imágenes que cargaba para, mostrar un mensaje, ir a una dirección de Internet... esto lo hacia de forma estática y en tiempo de ejecución mostraba la imagen mediante el Bitmap.LoadFromFile().
Con ganas de mejorar quiero hacer esto mismo pero dinamicamente:

procedure TForm1.Button1Click(Sender: TObject);
var
ListadeObjetos: Tlist;
I: Integer;

begin

ListadeObjetos := Tlist.Create();

for I := 0 to 3 do
begin
ListadeObjetos.Add(TImage.Create(Form1));

with TImage(ListadeObjetos.Items[I]) do
begin
Parent := HorzScrollBox1;
Height := 100;
Width := 100;
Bitmap.LoadFromFile(GetCurrentDir + '\' + (I + 1).ToString + '.png');
with Margins do
begin
Bottom := 5;
Left := 5;
Right := 5;
Top := 5;
end;

MarginWrapMode := MarginWrapMode.iwStretch;
Align := Align.alLeft;
OnClick := pppClick;
end;

end;

end;



public
{ Public declarations }
procedure pppClick(Sender: TObject);



procedure TForm1.pppClick(Sender: TObject);
begin
showmessage('prueba Imagen:');
end;


Al ejecutar lo que consigo es siempre el mismo mensaje ''prueba Imagen' pero mi intención es que cada imagen que creo le pase (no se como) un showmessage('Timage:'+xx ) diferente a la propiedad OnClick.

¿Pueden echarme una mano con esto por favor?.

Neftali [Germán.Estévez]
25-06-2018, 08:56:49
Al ejecutar lo que consigo es siempre el mismo mensaje ''prueba Imagen' pero mi intención es que cada imagen que creo le pase (no se como) un showmessage('Timage:'+xx ) diferente a la propiedad OnClick.


Para ello puedes usar el parámetro Sender, que será diferente para cada imagen sobre la que pulses. En realidad ese Sender será exactamente el componente TImage sobre el que has pulsado.
Lo único que debes hacer es realizar un CAST del objeto Sender para poder utilizarlo.
Cambia tu código y prueba esto:



procedure TForm1.pppClick(Sender: TObject); begin
if (Sender = TImage) then begin
showmessage('prueba Imagen: ' + TImage(Sender).Name);
end;
end



Igual que he accedido à la propiedad Name, puede acceder al resto del componente.

barakuda
25-06-2018, 11:05:17
Muchas gracias Neftali por tu ayuda, la modificación que me sugeriste me daba error:

[dcc32 Error] uni_LO.pas(83): E2015 Operator not applicable to this operand type

Lo modifique:
if (Sender = TImage(sender)) then ....

y ahora me funciona.


dejo el código por si a otro compañero le ocurre lo mismo.

....
private
{ Private declarations }

procedure pppClick(Sender: TObject);
...

procedure TForm1.Button1Click(Sender: TObject);
var
ListadeObjetos: Tlist;
I: Integer;

begin

ListadeObjetos := Tlist.Create();

for I := 0 to 3 do
begin
ListadeObjetos.Add(TImage.Create(Form1));

with TImage(ListadeObjetos.Items[I]) do
begin
Parent := HorzScrollBox1;
Height := 100;
Width := 100;
Bitmap.LoadFromFile(GetCurrentDir + '\' + (I + 1).ToString + '.png');
with Margins do
begin
Bottom := 5;
Left := 5;
Right := 5;
Top := 5;
end;
Name:='Imagen'+(i+1).ToString;
MarginWrapMode := MarginWrapMode.iwStretch;
Align := Align.alLeft;
OnClick := pppClick;

end;

end;

end;

procedure TForm1.pppClick(Sender: TObject);
begin
if (Sender = TImage(sender)) then begin
showmessage('prueba Imagen: ' + TImage(Sender).Name);
end;

end;



Nos obstante una consulta, si cada imagen fuera ligada a una url, una reproducción de sonido, otra imagen etc... es decir a algo mas trascendente ¿seria posible asignar ese "evento" a su correspondiente imagen cuando se crea el objeto TImage?, me explico...

En una BBDD tenemos X fotos esas fotos están ordenadas y se corresponden con el sonido Y cuya dirección esta almacenada también en la BBDD de manera que:
Foto1 -> c:\.....\animales\leonsabana.wav
Foto2 -> c:\.....\motorV6.wav
...

Corrígeme por favor si me equivoco, para conseguir esto, como TImagen no tiene una propiedad para almacenar texto, ¿debería sobrecargar la clase?.

De nuevo muchas gracias por echarme una mano.

Neftali [Germán.Estévez]
25-06-2018, 12:15:52
Perdón. He cometido un error en el código al escribirlo.
En lugar de esto:



procedure TForm1.pppClick(Sender: TObject);

begin
if (Sender = TImage) then begin
showmessage('prueba Imagen: ' + TImage(Sender).Name);
end;
end;




Quería poner esto (es importante el operador IS en lugar del =):



procedure TForm1.pppClick(Sender: TObject);

begin
if (Sender is TImage) then begin
showmessage('prueba Imagen: ' + TImage(Sender).Name);
end;
end;




Con eso comprobamos que el Sender sea de la clase correcta.
No debería, pero eso evita que falle la línea siguiente al realizar el CAST:



...
TImage(Sender)
...

Neftali [Germán.Estévez]
25-06-2018, 12:24:17
Corrígeme por favor si me equivoco, para conseguir esto, como TImagen no tiene una propiedad para almacenar texto, ¿debería sobrecargar la clase?.



No la tienen, como bien dices.
Si con un Integer te vale, los TImage y el resto de componentes poseen una propiedad genérica para estas cosas llamada Tag. Que los programadores solemos usar para estas cosas.


La otra opción, como bien dices, es ampliar la clase para añadir esa propiedad.

barakuda
25-06-2018, 12:54:12
De nuevo gracias por la sugerencia y aclaración, no pensé en la propiedad Tag la cual se podría utilizar como una especie de puntero hacia a una lista.

Muchas gracias por tu ayuda.^\||/

cloayza
26-06-2018, 20:04:33
Estimado barakuda, si me permite le propongo otra opción...

Este método lo he usado cuando requiero mostrar imagenes en algunas aplicaciones...

Consiste en utilizar un TListview y TImageList...


unit Unit2;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, Vcl.ImgList,
Vcl.ExtCtrls, Vcl.Imaging.pngimage;

type
{Tipo de datos que usted puede definir para incorporar mas detalles a cada imagen}
PInfoImg=^TInfoImg;
TInfoImg=Record
Title:string;
Description:string;
FileName:string;
Url:string;
End;

TForm2 = class(TForm)
ImageList: TImageList;
ListView: TListView;
Label1: TLabel;
AddImagen: TButton;
DeleteImagen: TButton;
lblTitle: TLabel;
lblDescription: TLabel;
lblFilename: TLabel;
lblUrl: TLabel;
procedure Button1Click(Sender: TObject);
procedure ListViewSelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
private
{ Private declarations }
public
{ Public declarations }
function CreateBitmap(Filename:string):TBitmap;
end;

var
Form2: TForm2;

implementation

{$R *.dfm}

{Esta función crea un bitmap a partir de un nombre de archivo de imagen
}
function TForm2.CreateBitmap(Filename:string):TBitmap;
var
picture:TPicture;
begin
Try
picture:=TPicture.Create;
picture.LoadFromFile(Filename);

Result := TBitmap.Create;
Result.Assign(Picture.Graphic);

picture.Free;
except
Result:=nil;
End;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
Listview.LargeImages:=ImageList;
Listview.ViewStyle :=vsIcon;
end;

procedure TForm2.AddImagenClick(Sender: TObject);
var
FileName:string;
imgInfo:PInfoImg;
begin
if not PromptForFileName(Filename,'Png (*.png)|*.png|Bitmap (*.bmp)|*.bmp',
'*.png','Agregar imagen','',false) then
Exit;
{Agrego la imagen a el ImageList...}
ImageList.Add( CreateBitmap(FileName), nil);

{Creo un puntero para almacenar mas información}
imgInfo:=New(PInfoImg);
imgInfo^.Title :=Format('Imagen %d',[ListView.Items.Count]);
imgInfo^.Description:=Format('Descripción Imagen %d',[ListView.Items.Count]);
imgInfo^.FileName :=Filename;
imgInfo^.Url :=Format('https://www.google.com?img=%s',[extractfilename(filename)]);

with ListView.Items.Add do
begin
{Agrego un item y asigno el Title a Caption}
Caption:=imgInfo^.Title;
{En Data asigno el puntero con la informacion de la imagen}
Data:=imgInfo;
{Asigno el indice de la imagen}
ImageIndex:=ImageList.Count-1;
end;
end;

procedure TForm2.ListViewSelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
begin
{Cada vez que pincho un item del Listview recupero los datos desde Item.Data}
lblTitle.Caption :=PInfoImg(Item.Data)^.Title;
lblDescription.Caption:=PInfoImg(Item.Data)^.Description;
lblFilename.Caption :=PInfoImg(Item.Data)^.FileName;
lblUrl.Caption :=PInfoImg(Item.Data)^.Url;
end;
end.


La imagen adjunta muestra el resultado...
https://www.mnssimulacion.cl/~cloayza/pub/barakuda.gif

Espero le ayude...
Saludos cordiales

cloayza
26-06-2018, 20:53:03
Estimado barakuda, no me percate que era en foro de Firemonky, talvez el código que le indique no funcione correctamente...:(