I created several new objects
TMyMemo = class (开发者_如何学JAVATMemo)
private
FYahoo = Integer;
procedure SetYahoo(Value:integer)
public
procedure Google(A,B:integer; S:string);
published
property Yahoo:integer read FYahoo write SetYahoo;
end;
TMyPaintbox = class (TPaintbox)
private
FYahoo = Integer;
procedure SetYahoo(Value:integer)
public
procedure Google(A,B:integer; S:string);
published
property Yahoo:integer read FYahoo write SetYahoo;
end;
TMyButton = class (TButton)
private
FYahoo = Integer;
procedure SetYahoo(Value:integer)
public
procedure Google(A,B:integer; S:string);
published
property Yahoo:integer read FYahoo write SetYahoo;
end;
. . .
These Controls are placed on Form1. Is there a way, how can I change the same property (Yahoo) and run the procedure (Google), which is declared in different objects in general?
I do not want to manually check class type like: if Controls[i] is TMyMemo then ... if controls[i] is TMyPaintbox then ...
because I do not know how many of my new classes will have property Yahoo and method Google (This is only simple example). Probably I have to use ^ and @ operator or FieldAdress, MethodAddress I do not know what else. Can you help me find general solution?
procedure Form1.Button1Click(Sender:TObject);
var i:integer;
begin
for i:=0 to Form1.ControlCount-1 do
begin
Controls[i].Google(4,5, 'Web'); // this should be changed somehow
Controls[i].Yahoo:=6; // this should be changed somehow
end;
end;
end;
Thanks
Define an interface which has both method Google() and property Yahoo defined.
Make your TMyButton, TMyMemo and TMyPaintbox inherit from that interface and override those methods to do what is necessary.
In the loop, cast the controls to the interface type using the "as" operator and access the Yahoo field and Google() method.
Here is the code - The is operator doesnt work as intended in Delphi 2009 and below, so I had to write a function for that - It needs to rely on catching a cast exception, so it isn't the cleanest solution:
type
TMyInterface = interface(IInterface)
['{1F379072-BBFE-4052-89F9-D4297B9A826F}']
function GetYahoo : Integer;
procedure PutYahoo(i : Integer);
property Yahoo : Integer read GetYahoo write PutYahoo;
procedure Google(A, B : integer; S : string);
end;
TMyButton = class (TButton, TMyInterface)
private
FStr : String;
FYah : Integer;
public
function GetYahoo : Integer;
procedure PutYahoo(i : Integer);
procedure Google(A, B : integer; S : string);
end;
TMyMemo = class (TMemo, TMyInterface)
private
FStr : String;
FYah : Integer;
public
function GetYahoo : Integer;
procedure PutYahoo(i : Integer);
procedure Google(A, B : integer; S : string);
end;
{ TMyButton }
function TMyButton.GetYahoo: Integer;
begin
Result := 0;
end;
procedure TMyButton.Google(A, B: integer; S: string);
begin
FStr := S + '=' + IntToStr(A + B);
end;
procedure TMyButton.PutYahoo(i: Integer);
begin
FYah := 42;
end;
{ TMyMemo }
function TMyMemo.GetYahoo: Integer;
begin
//
end;
procedure TMyMemo.Google(A, B: integer; S: string);
begin
//
end;
procedure TMyMemo.PutYahoo(i: Integer);
begin
//
end;
function IsMyIntf(c : TControl) : TMyInterface;
begin
try
Result := c as TMyInterface;
except on e : Exception do
Result := nil;
end;
end;
procedure TForm2.Button1Click(Sender: TObject);
var
i: Integer;
p : TMyInterface;
begin
for i := 0 to ControlCount - 1 do
begin
p := IsMyIntf(Controls[i]);
if (p <> nil) then
begin
p.PutYahoo(i);
p.Google(i, i, 'Hah!');
end;
end;
end;
- Use the same base class
- Use an interface
- Use the D2010 RTTI
- Implement a custom message on all controls and process it.
@lyborko, the Controls[i] returns a TControl Class wich not have an implementation for the Google
method and the Yahoo
property.for resolve you problem, you can check the class of the Controls[i]
using the ClassType
property and then implement something like this.
procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
begin
for i:=0 to Form1.ControlCount-1 do
begin
if Controls[i].ClassType = TMyPaintbox then
begin
TMyPaintbox (Controls[i]).Google(4,5, 'Web');
TMyPaintbox (Controls[i]).Yahoo:=6;
end
else
if Controls[i].ClassType = TMyMemo then
begin
TMyMemo (Controls[i]).Google(4,5, 'Web');
TMyMemo (Controls[i]).Yahoo:=6;
end
else
if Controls[i].ClassType = TMyButton then
begin
TMyButton (Controls[i]).Google(4,5, 'Web');
TMyButton (Controls[i]).Yahoo:=6;
end;
end;
end;
Better that use IF...ELSE with differents classes for know the component class you can use RTTI to know if an object has a específic property. You can find the code and explanation here:
Modify control properties using RTTI
Here you can find more code for access properties of a component using RTTI.
Regards.
You are propobly looking for RTTI.
Se this article about that http://delphi.about.com/od/vclusing/a/coloringfocused.htm (look at page 3)
The Only problem is that it Can't se public properties/methods, only published (i don't know if that stil is true in delphi 2010). A lot of RTTI info for delphi 2010 can be found here http://robstechcorner.blogspot.com/2009/09/so-what-is-rtti-rtti-is-acronym-for-run.html .
Calling a method by name (via RTTI): Se http://delphi.about.com/cs/adptips2004/a/bltip0204_3.htm
精彩评论