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

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

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

Ответить
wwswowsogon
постоялец
Сообщения: 157
Зарегистрирован: 23.12.2008 19:41:37

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

Сообщение wwswowsogon »

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

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

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

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


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

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

...

procedure TForm1.LabelClick();
begin

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

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

Не ругайтесь особо, плохо знаю эту тему.
Аватара пользователя
runewalsh
энтузиаст
Сообщения: 579
Зарегистрирован: 27.04.2010 00:15:25

Сообщение runewalsh »

Через поля TForm1. Это указатель на самом деле не на просто функцию, а на метод — он физически хранит два указателя, на функцию и на self, запоминаемый в момент @.
svk12
постоялец
Сообщения: 411
Зарегистрирован: 09.06.2008 18:42:47

Сообщение 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;

Как-то так.
wwswowsogon
постоялец
Сообщения: 157
Зарегистрирован: 23.12.2008 19:41:37

Сообщение wwswowsogon »

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, насколько я могу судить, это не описано.
RRYTY
постоялец
Сообщения: 253
Зарегистрирован: 25.12.2021 09:00:32

Сообщение RRYTY »

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

label_index := (Self as TLabel).Tag;
Учебник, в данном случае, нужен по FreePascal.
svk12
постоялец
Сообщения: 411
Зарегистрирован: 09.06.2008 18:42:47

Сообщение svk12 »

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

procedure TForm1.LabelClick(Sender :TObject);
begin

  label_index := Self.Tag;

end;
Self - объект, которому принадлежит метод, в данном случае - экземпляр класса TForm1.
Объект, вызвавший обработчик, передаётся через параметр Sender.
RRYTY
постоялец
Сообщения: 253
Зарегистрирован: 25.12.2021 09:00:32

Сообщение RRYTY »

svk12 писал(а):Объект, вызвавший обработчик, передаётся через параметр Sender.
Да, верно, это я ошибся. :(
wwswowsogon
постоялец
Сообщения: 157
Зарегистрирован: 23.12.2008 19:41:37

Сообщение wwswowsogon »

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 в методе класса.
Ответить