在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
之后的()
。
有时代码会充满类似的functions
和procedures
,因为我们需要使用我们无法指定的类似视觉控件执行相同的操作。
这只是一个使用示例。通常我会在更复杂的代码上使用这些代码来实现许多控件和其他类型对象的标准目标。
是否有替代或技巧可以使这些任务更加灵活?
答案 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';
您必须确保放在此处的所有对象都使用相同的方法内部,否则您的应用程序将以神秘的方式破解。