Как вытянуть значение свойства динамически созданного компонента при клике на нем?

Wrackage

Здравствуйте, товарищи программисты! Возникла проблема, которую никак не могу разрешить сам, помогите, пожалуйста. Есть форма, на которой при ее создании и появлении в runtime, в зависимости от внешних условий, динамически создается некоторое количество Label-ов. Их может быть 2, а может и 152, заранее неизвестно. В свойства динамически создаваемых Label-ов ранее прописываются все необходимые значения, в том числе и Caption, а в свойство Tag записывается число. Внимание вопрос: как реализовать функционал, при котором, после показа формы, клик на одном из динамически созданных Label-ов (юзер может кликнуть на любом) вытягивал бы значение из свойства Tag кликнутого Label-а и передавал его в некоторую переменную "number".P.S.: Не могу разобраться как можно это сделать при помощи обычной процедуры OnClick Вот кусок кода, динамически создающий Label-ы:
type
    TNotificationType = (New, Changed);
var
    notifications: array of TLabel;
    u: integer = 0;
 
procedure Add_Notification(task_id: integer; notification_type: TNotificationType;
                          notification_text: string);
var
    j: integer;
begin
    notifications[u]:= TLabel.Create(FormNotification);
    notifications[u].Parent:= FormNotification;
    notifications[u].AutoSize:= True;
    notifications[u].ParentFont:= False;
    if notification_type = New then
        begin
            notifications[u].Caption:= 'Новое задание!' +#13+ notification_text;
            notifications[u].Font.Color:= clMaroon;
            notifications[u].Font.Style:= [fsBold];
        end
    else
        begin
            notifications[u].Caption:='Изменено задание №'+IntToStr(task_id)+#13+notification_text;
            notifications[u].Font.Color:= clHighlight;
        end;
    notifications[u].Cursor:= crHandPoint;
    notifications[u].Hint:= 'Нажмите, чтобы перейти к выбранному заданию.';
    notifications[u].ShowHint:= True;
    notifications[u].Tag:= task_id;
    notifications[u].OnClick:= Notification_Label_Click;
    notifications[u].WordWrap:= True;
    notifications[u].Left:= 5;
    
    u:= u + 1;
end;
3 ответа

Wrackage

В Sender передаётся лейбл на котором кликнули
procedure TFormNotification.Notification_Label_Click(Sender: TObject);
begin
  number := (Sender as TLabel).Tag;
end;


Wrackage

Спасибо большое за подсказку, не знал про подобные финты с оператором "as". Но вот возникла другая проблема: компилятор ругается на строку
notifications[u].OnClick:= Notification_Label_Click;
Говорит: [Error] UnitFunctionsAndProcedures.pas(68): Incompatible types: 'method pointer and regular procedure'Я почитал про method pointer-ы и нашел пример оформления и их использования, которые применяются в динамически создаваемых компонентах:
//Given the declarations
type
  TNotifyEvent = procedure(Sender: TObject) of object;
  TMainForm = class(TForm)
    procedure ButtonClick(Sender: TObject);
    ...
  end;
var
  MainForm: TMainForm;
  OnClick: TNotifyEvent
 
//we could make the following assignment.
 
OnClick := MainForm.ButtonClick;
Но в моем случае никак не получается это оформить корректно У меня код, отвечающий за динамическое создание Label-ов и обработку кликов на них, вынесен в отдельный модуль. Пожалуйста, подскажите как правильно оформить объявление и описание method pointer-ов в моем случае, чтобы не ругался компилятор. Мой модуль:
unit UnitFunctionsAndProcedures;
 
interface
    function Get_Database_Directory(const alias: string): string;
    function Copy_Files(target_files: array of string; destination: string): Integer;
    function Sync_Databases: string;
 
implementation
uses
    DBTables, DBiTypes, ShellApi, DB, SysUtils, StdCtrls, Graphics, Controls,
    FormTasklistBrowse, FormAddTaskUnit, OverlordDataModule, FormWaitSynchronization,
    FormNotificationUnit;
type
    TNotificationType = (New, Changed);
    TNotifyEvent = procedure(Sender: TObject) of object;//<- Такой вариант не решил проблему
var
    notifications: array of TLabel;
    u: integer = 0;
    OnClick: TNotifyEvent;                         //<- Такой вариант не решил проблему
 
procedure Notification_Label_Click(Sender: TObject);
begin
    FormBrowse.Edit1.Text:= IntToStr( (Sender as TLabel).Tag );
end;
 
 
procedure Add_Notification(task_id: integer; notification_type: TNotificationType;
                          notification_text: string);
var
    j: integer;
begin
    notifications[u]:= TLabel.Create(FormNotification);
    notifications[u].Parent:= FormNotification;
    notifications[u].AutoSize:= True;
    notifications[u].ParentFont:= False;
    if notification_type = New then
        begin
            notifications[u].Caption:= 'Новое задание!' +#13+ notification_text;
            notifications[u].Font.Color:= clMaroon;
            notifications[u].Font.Style:= [fsBold];
        end
    else
        begin
            notifications[u].Caption:='Изменено задание №'+IntToStr(task_id)+#13+notification_text;
            notifications[u].Font.Color:= clHighlight;
        end;
    notifications[u].Cursor:= crHandPoint;
    notifications[u].Hint:= 'Нажмите, чтобы перейти к выбранному заданию.';
    notifications[u].ShowHint:= True;
    notifications[u].Tag:= task_id;
    notifications[u].OnClick:= Notification_Label_Click;  // ТУТ РУГАЕТСЯ КОМПИЛЯТОР
    notifications[u].WordWrap:= True;
    notifications[u].Left:= 5;
    notifications[u].Top:= 0;
    if High(notifications) <> 0 then
        begin
           for j:= 0 to High(notifications) do
              notifications[u].Top:= notifications[u].Top + 5 + notifications[j].Height;
        end
    else
        notifications[u].Top:= 5;
    u:= u + 1;
end;
 
 
function Copy_Files(target_files: array of string; destination: string): Integer;
begin
     {Инструкции функции...}
end;
 
function Sync_Databases: string;
begin
    {Инструкции функции...}
end;
 
function Get_Database_Directory(const alias: string): string;
begin
    {Инструкции функции...}
end;
 
end.


Wrackage

TNotifyEvent = procedure(Sender: TObject) of object;
т.е. процедура, обрабатывающая это событие должна быть методом какого-то класса, как самое простое - объявите ее как метод одной из форм, которая доступна в этом модуле (необходимо, чтобы экземпляр этой формы уже был создан перед обращением к процедуре создания лейблов)
FormTasklistBrowse, FormAddTaskUnit, ... FormWaitSynchronization, FormNotificationUnit