如何一次使用“Asder”参数和“As”运算符多个类?

时间:2012-07-04 22:00:01

标签: delphi oop sender as-operator

在Delphi中,有时我们需要这样做......

function TForm1.EDIT_Click(Sender: TObject);
begin
  (Sender As TEdit).Text := '';
end;

...但有时我们需要用其他对象类重复该函数,如...

function TForm1.COMBOBOX_Click(Sender: TObject);
begin
  (Sender As TComboBox).Text := '';
end;

...因为运营商As不接受灵活性。它必须知道该类才能允许.Text之后的()

有时代码会充满类似的functionsprocedures,因为我们需要使用我们无法指定的类似视觉控件执行相同的操作。

这只是一个使用示例。通常我会在更复杂的代码上使用这些代码来实现许多控件和其他类型对象的标准目标。

是否有替代或技巧可以使这些任务更加灵活?

7 个答案:

答案 0 :(得分:11)

使用RTTI在不相关类的类似命名属性上执行常见任务,例如:

Uses
 ..., TypInfo;

// Assigned to both TEdit and TComboBox
function TForm1.ControlClick(Sender: TObject);
var
  PropInfo: PPropInfo;
begin
  PropInfo := GetPropInfo(Sender, 'Text', []);
  if Assigned(PropInfo) then
    SetStrProp(Sender, PropInfo, '');
end;

在某些情况下,某些控件使用Text而某些控件使用Caption代替,例如;

function TForm1.ControlClick(Sender: TObject);
var
  PropInfo: PPropInfo;
begin
  PropInfo := GetPropInfo(Sender, 'Text', []);
  if not Assigned(PropInfo) then
    PropInfo := GetPropInfo(Sender, 'Caption', []);
  if Assigned(PropInfo) then
    SetStrProp(Sender, PropInfo, '');
end;

答案 1 :(得分:9)

您可以使用is运算符,尝试此示例

 if Sender is TEdit then
  TEdit(Sender).Text:=''
 else
 if Sender is TComboBox then
  TComboBox(Sender).Text:='';

答案 2 :(得分:5)

您可以使用绝对关键字来消除混乱的类型转换,该关键字允许您声明占用相同内存位置的不同类型的变量,在这种情况下与事件参数的位置相同。 / p>

您仍然需要使用“is”执行类型检查,但在其他方面,这种方法更清洁,但同样安全。

procedure TMyForm.ControlClick(Sender: TObject);
var
  edit: TEdit absolute Sender;
  combo: TComboBox absolute Sender;
   :
begin
  if Sender is TEdit then
    edit.Text := ''
  else if Sender is TComboBox then
    combobox.Text := ''
  else
   :
end;

我差不多3年前在我的博客中写过in more detail about using this language feature

答案 3 :(得分:2)

我发表评论作为答案,因为我在这里没有看到任何答案。 SetTextBuf是TControl的公共方法。该方法用于通过SetText窗口消息填充内部文本数据成员。这就是TControl后代更新Caption和Text属性的方式。所以所有TControl后代,如TButton,TEdit,TComboBox都将使用以下类型的代码。而且您不必使用RTTI。

function TForm1.EDIT_Click(Sender: TObject);
begin
  (Sender as TControl).SetTextBuf('Text or Caption'); // will work for both the Caption and text property
end;

答案 4 :(得分:1)

我不知道你是否正在使用tag属性,但它对这些情况很有用。将所有Tedits的标记设置为1并将所有Tcombobox的标记设置为2等可以让您这样做:

if Sender is TControl then
  Case TControl(Sender).tag of
    1: TEdit(sender).text := '';
    2: Tcombobox(sender).text := '';
    3....etc
  end;

只是一个想法,它看起来更整洁,更容易阅读/调试:)

答案 5 :(得分:0)

感谢你们,特别是@RemyLebeau,我可以制作适用于任何类型的Win Control或数据库控制的通用功能。它将控件变为红色(或任何你想要的颜色),如果它是必需的但是空的,如果它在数据库上有重复的信息,或者我们想要检查的任何其他条件。它返回数字而不是true或false,因此我们只能在许多检查结束时发送一条消息,并告诉用户他/她做了多少错误。

function CheckInput(Control: TWinControl; Condition: Boolean; EmptyState: Integer; Msg: String): Integer;
var
  PropInfo: PPropInfo;
begin
{ os controles que precisam passar por condições para que seu conteúdo seja aceito }
  Result := 0;
  if EmptyState = ciNotEmpty then
  begin
    PropInfo := GetPropInfo(Control, 'Text', []);
    if Assigned(PropInfo) then
    begin
      if GetStrProp(Control, PropInfo) = '' then
      begin
        Condition := False;
        Msg := ciEmptyMsg;
      end;
    end;
  end;
  if not Condition then
  begin
    Result := 1;
    PropInfo := GetPropInfo(Control, 'Color', []);
    if Assigned(PropInfo) then SetPropValue(Control, PropInfo, ciErrorColor);
    if Msg <> '' then ShowMessage(Msg);
  end
  else
  begin
    PropInfo := GetPropInfo(Control, 'Color', []);
    if Assigned(PropInfo) then SetPropValue(Control, PropInfo, ciNormalColor);
  end;
end;

答案 6 :(得分:-1)

如果你一直走下去,你会注意到TEdit和TCombobox都来自TControl。如果您查看他们使用哪种方法设置文本,那么您将看到它是TControl实现的方法。这就是为什么你可以做一些丑陋的事情:

if (sender is TEdit) or (sender is TComboBox) then
  TEdit(sender).Text:='test';

您必须确保放在此处的所有对象都使用相同的方法内部,否则您的应用程序将以神秘的方式破解。