Как получить доступ к свойству компонента, на который ссылается параметр Sender (компонент, вызвавший событие) - PullRequest
1 голос
/ 01 августа 2020

Я новичок в delphi и pascal, и мне было интересно, есть ли способ получить / получить доступ к свойству компонента, на который отправитель ссылается в рамках процедуры.

Более конкретно, я бы хотелось бы создать процедуру, которая изменяет свойство caption метки, причем эта метка является компонентом, на который ссылается Sender . Я предполагаю, что эта процедура выглядит примерно так:

procedure TForm1.LabelEdit(Sender: TObject);
begin
    Sender.caption := 'Sample Text';
end;

Естественно, это не сработает, но можно ли сделать что-то подобное или что-то подобное?

Ответы [ 2 ]

3 голосов
/ 01 августа 2020

Хотя пример в вашем вопросе на самом деле не имеет смысла (он неверно предполагает, что TLabel имеет событие OnEdit), очень возможно использовать параметр Sender для получения информации об отправителе.

Создайте новое приложение VCL и поместите в форму несколько TLabel элементов управления. Дайте им разные подписи (например, Dog, Cat, Rabbit, Horse et c.).

Теперь выберите их все в конструкторе форм и затем используйте объект Инспектор , чтобы создать для них общий обработчик OnClick. Вы можете назвать его LabelClick (напишите LabelClick в поле редактирования рядом с OnClick и нажмите Введите ).

Это создаст следующий пустой метод:

procedure TForm1.LabelClick(Sender: TObject);
begin

end;

Имеет параметр Sender типа TObject. Теперь, в зависимости от того, как вызывается этот метод, Sender может быть любым TObject (кнопка, форма, растровое изображение, ...) или nil (вообще без объекта).

Но в нашем случае мы ожидаем, что этот метод в основном будет вызываться в ответ на нажатие меток, и в этих случаях Sender будет соответствующим объектом TLabel.

Попробуем отображать заголовок нажатой метки в окне сообщения!

Мы пробуем

procedure TForm1.LabelClick(Sender: TObject);
begin
  ShowMessage(Sender.Caption); // won't compile!
end;

Но это даже не компилируется! Проблема в том, что TObject не имеет участника publi c Caption. Но TLabel делает, поэтому мы можем написать

procedure TForm1.LabelClick(Sender: TObject);
begin
  ShowMessage(TLabel(Sender).Caption);
end;

Здесь мы говорим компилятору, что знаем, что Sender всегда будет TLabel, и мы просим его Предположим, что это так.

Но это вызовет sh или сделает другие плохие вещи, если каким-то образом этот метод будет вызван с не- TLabel Sender. Так что безопаснее сделать

procedure TForm1.LabelClick(Sender: TObject);
begin
  ShowMessage((Sender as TLabel).Caption);
end;

. Это будет то же самое, за исключением того, что теперь компилятор создаст код, который проверяет во время выполнения, что Sender действительно является объектом TLabel. Если нет, код вызовет исключение. Это намного лучше, чем проблемы с повреждением памяти / AV, которые могут возникнуть с небезопасным приведением выше. во время выполнения. Если это метка, мы отображаем ее заголовок. В противном случае мы предпочитаем ничего не делать. Обратите внимание, что здесь нет смысла использовать безопасный (и немного, немного медленнее) as cast.

1 голос
/ 01 августа 2020

Вы приводите Sender к типу, с которым связано событие.

procedure TForm1.Button1Click(Sender: TObject);
begin
  (Sender as TButton).Caption := 'Clicked';
end;

Если вы разделяете событие между различными типами элементов управления, вы можете сначала проверить, какой это тип:

procedure TForm1.ControlClick(Sender: TObject);
begin
  if (Sender is TEdit) then
    TEdit(Sender).Text := 'Clicked'
  else if (Sender is TButton) then
    TButton(Sender).Caption := 'Clicked';
end;
  
end;
...