Передача параметров через указатель на функцию

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Передача параметров через указатель на функцию

Сообщение wwswowsogon » 13.11.2023 23:22:41

Всем доброго времени суток!

Есть массив динамически создаваемых стандартных контролов, например, из TLabel.

На обработчик событий этих объектов, например, OnClick, повешен указатель на какую-то функцию / процедуру.

Код: Выделить всё

arr_label[i] := TLabel.Create(Self);

...
                   
arr_label[i].OnClick := @LabelClick;

...

procedure TForm1.LabelClick();
begin

  //здесь нам потребуется индекс(ы) массива
end;



Как передать в эту функцию переменную, например, индекс конкретного label'a?
Возможен ли это вообще такой вариант?

Не ругайтесь особо, плохо знаю эту тему.
wwswowsogon
постоялец
 
Сообщения: 152
Зарегистрирован: 23.12.2008 20:41:37

Re: Передача параметров через указатель на функцию

Сообщение runewalsh » 14.11.2023 00:11:30

Через поля TForm1. Это указатель на самом деле не на просто функцию, а на метод — он физически хранит два указателя, на функцию и на self, запоминаемый в момент @.
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Re: Передача параметров через указатель на функцию

Сообщение svk12 » 14.11.2023 02:29:13

Код: Выделить всё
arr_label[i] := TLabel.Create(Self);
arr_label[i].Tag:=i;
...
                   
arr_label[i].OnClick := @LabelClick;

procedure TForm1.LabelClick();
begin
  i:=(Sender as TLabel).Tag;
  //здесь нам потребуется индекс(ы) массива
end;



Как-то так.
svk12
постоялец
 
Сообщения: 408
Зарегистрирован: 09.06.2008 18:42:47

Re: Передача параметров через указатель на функцию

Сообщение wwswowsogon » 14.11.2023 11:01:36

svk12 писал(а):
Код: Выделить всё
arr_label[i] := TLabel.Create(Self);
arr_label[i].Tag:=i;
...
                   
arr_label[i].OnClick := @LabelClick;

procedure TForm1.LabelClick();
begin
  i:=(Sender as TLabel).Tag;
  //здесь нам потребуется индекс(ы) массива
end;



Как-то так.


Да, это решение, спасибо большое. Я много лет думал, для чего нужно свойство Tag у компонента. Теперь это стало понятно :D

runewalsh писал(а):Через поля TForm1. Это указатель на самом деле не на просто функцию, а на метод — он физически хранит два указателя, на функцию и на self, запоминаемый в момент @.


Не совсем понял, как это. Можно, конечно, прописать переменную в полях формы, и потом использовать в процедуре, но она никак не привязана в данном случае к индексу потому что индекс мы получаем при только при событии:

Код: Выделить всё

TForm1 = class(TForm)

...

  private

    label_index: Word;
  public

...

arr_label[i] := TLabel.Create(Self);

label_index := i;

arr_label[i].Name := 'arr_label' + IntToStr(i);
arr_label[i].Parent := Form1;

...

procedure TForm1.LabelClick();
begin

  ShowMessage(IntToStr(label_index));

end;


Уцепивщись за фразу
на self, запоминаемый в момент @.
, пробовал сделать так:

Код: Выделить всё

procedure TForm1.LabelClick();
begin

  label_index := Self.Tag;

end;



Но в таком случае выдаётся неверный результат.

Где вообще можно почитать про все эти механизмы? В наших любимых учебниках по Lazarus, насколько я могу судить, это не описано.
wwswowsogon
постоялец
 
Сообщения: 152
Зарегистрирован: 23.12.2008 20:41:37

Re: Передача параметров через указатель на функцию

Сообщение RRYTY » 14.11.2023 11:19:24

Код: Выделить всё
label_index := (Self as TLabel).Tag;

Учебник, в данном случае, нужен по FreePascal.
RRYTY
постоялец
 
Сообщения: 208
Зарегистрирован: 25.12.2021 10:00:32

Re: Передача параметров через указатель на функцию

Сообщение svk12 » 14.11.2023 13:45:43

Код: Выделить всё
procedure TForm1.LabelClick(Sender :TObject);
begin

  label_index := Self.Tag;

end;

Self - объект, которому принадлежит метод, в данном случае - экземпляр класса TForm1.
Объект, вызвавший обработчик, передаётся через параметр Sender.
svk12
постоялец
 
Сообщения: 408
Зарегистрирован: 09.06.2008 18:42:47

Re: Передача параметров через указатель на функцию

Сообщение RRYTY » 14.11.2023 17:13:14

svk12 писал(а):Объект, вызвавший обработчик, передаётся через параметр Sender.


Да, верно, это я ошибся. :(
RRYTY
постоялец
 
Сообщения: 208
Зарегистрирован: 25.12.2021 10:00:32

Re: Передача параметров через указатель на функцию

Сообщение wwswowsogon » 15.11.2023 00:06:04

RRYTY писал(а):Учебник, в данном случае, нужен по FreePascal.


Безусловно, язык знать получше мне бы не помешало. :) Но всё же сущности типа Self, Sender, Tag и т. д. и т. п. больше относятся к Delphi / Lazarus / VCL. Всегда плохо понимал, что всё это значит и как его использовать. Но до сей поры и не требовалось.

svk12 писал(а):
Код: Выделить всё
procedure TForm1.LabelClick(Sender :TObject);
begin

  label_index := Self.Tag;

end;

Self - объект, которому принадлежит метод, в данном случае - экземпляр класса TForm1.
Объект, вызвавший обработчик, передаётся через параметр Sender.


Спасибо всем за разъяснения, из них многое стало понятным. :)

Добавлено спустя 40 минут 11 секунд:
Почитал статьи на тему Self и Sender.

Насколько я понял, записи
Код: Выделить всё
procedure TForm1.LabelClick(Sender :TObject);
begin

  label_index := Tag;

end;

и
Код: Выделить всё
procedure TForm1.LabelClick(Sender :TObject);
begin

  label_index := Self.Tag;

end;

полностью равносильны. Просто обычно случаев Self не указывается (опускается) при манипуляциях внутри метода этого класса, указываются просто свойства / методы класса (например, класса формы). Self - это как $this в php :)

А если нам нужно внутри метода класса использовать свойство объекта другого класса (например, TLabel), мы используем конструкцию вида
Код: Выделить всё

label_index := (Sender as TLabel).Tag;


или
Код: Выделить всё

label_index := TLabel(Sender).Tag;


для чего и нужен параметр Sender в методе класса.
wwswowsogon
постоялец
 
Сообщения: 152
Зарегистрирован: 23.12.2008 20:41:37


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 23

Рейтинг@Mail.ru