想挑战自己吗?请利用RTTI技术帮我解决一个问题。200分。(200分)

  • 主题发起人 主题发起人 forgot2002
  • 开始时间 开始时间
F

forgot2002

Unregistered / Unconfirmed
GUEST, unregistred user!
打算写一个函数,利用Rtti技术,把某一个控件的一些指定的公用的可以在运行期修改的属性赋予另一个同类控件,函数原型如下:
CloneProperty(SourceComp,TargetComp:TComponent;Properties:TStrings):Boolean;
参数:SourceComp:源控件;
TargetComp:目标控件;
Properties:要克隆的属性字符串列表;
Boolean:如果克隆成功返回True,否则为False;
举例:
Properties中的String依次为'Caption','Hint','Left','Tag'
调用:CloneProperty(Button1,Button2,Properties)

请给出具体实现源码。不要只谈想法。
 
做个标记
 
function CloneProperty(SourceComp, TargetComp: TComponent; Properties: TStringList): Boolean;
var
i: integer;
v: Variant;
PropInfo: PPropInfo;
begin
result := True;
try
for i := 0 to Properties.Count - 1 do
begin
PropInfo := GetPropInfo(SourceComp.ClassInfo, Properties);
if ProPinfo <> nil then
begin
case PropInfo.PropType^.Kind of
tkString:
begin
v := GetStrProp(SourceComp, Properties);
SetStrProp(TargetComp, PropInfo, v);
end;
tkInteger:
begin
v := GetOrdProp(SourceComp, Properties);
SetOrdProp(TargetComp, PropInfo, v);
end;
// 可再加...
end;
end;
end;
except
result := False;
end;
end;

// 调用
procedure TForm1.Button3Click(Sender: TObject);
var
Properties: TStringList;
begin
Properties := TStringList.Create;
Properties.Add('Caption');
Properties.Add('Hint');
Properties.Add('Left');
CloneProperty(Button1, Button2, Properties);
Properties.Free;
end;

 
这个主意不错,向你学习。
 
楼上的兄弟,你给的代码我一早就写出来了,问题难就难在你写的// 可再加...这一段,你为什么
不写全呢?这是避重就轻的做法,对tkString,tkInteger的处理是很简单的,但对于其他类型,
就不一定很好处理,比如说对tkClass的处理,就是难点的所在,比如Font属性,是指向TFont对象,
还有PopMenu,是指向TPopupMenu对象,而对于这两种不同的类,你的处理方法有吗?我暂时有了
一个自己的想法,但还想征求多一点的意见。
 
呵呵,我是依葫芦画瓢,不过下面这样好像可以适用于你说的两种情况吧?还请指教[:)]

tkClass:
SetObjectProp(TargetComp, Properties, GetObjectProp(SourceComp, Properties));
 
uses TypInfo;

function CloneProperty(SourceComp,TargetComp:TObject;Properties:array of string):Boolean;
var
i:integer;
Value:Variant;
begin
for i:=Low(Properties) to High(Properties) do
begin
Value :=GetPropValue(SourceComp,Properties);
SetPropValue(TargetComp,Properties,Value);
end;
Result :=True;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
CloneProperty(Button1,Button2,['Left','Caption']);
end;
 
为了满足你的要求,修改上面的过程如下:
我想,基本上够了,只要属性的对象层次不超过2层,如果还要弄的话,可以递归。
function CloneProperty(SourceComp, TargetComp: TObject; Properties: array of string): Boolean;
var
i : integer;
Value : Variant;
P : PPropInfo;
PL : PPropList;
Obj : TObject;
begin
for i := Low(Properties) to High(Properties) do
begin
P := GetPropInfo(SourceComp, Properties);
if P.PropType^.Kind = tkClass then
begin
Obj := GetObjectProp(SourceComp, Properties);
SetObjectProp(TargetComp, Properties, Obj);
end
else
begin
Value := GetPropValue(SourceComp, Properties);
SetPropValue(TargetComp, Properties, Value);
end;
end;
Result := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
CloneProperty(Button1,Button2,['Left','Caption','Font']);
end;
 
问题的提出(感谢 forgot (让一切随风) 提出这个问题):
利用Rtti技术,把某一个控件的一些指定的公用的可以在运行期修改的属性赋予另一个同类控件,函数原型如下:
CloneProperty(SourceComp,TargetComp:TComponent;Properties:TStrings):Boolean;
参数:SourceComp:源控件;
TargetComp:目标控件;
Properties:要克隆的属性字符串列表;
Boolean:如果克隆成功返回True,否则为False;
举例:
Properties中的String依次为'Caption','Hint','Left','Tag'
调用:CloneProperty(Button1,Button2,Properties)?
//克隆对象属性,作者:Kingron,特别鸣谢ZsWang!
uses TypInfo;

function CloneProperty(SourceComp, TargetComp: TObject; Properties: array of string): Boolean;
var
i : integer;
begin
Result := True;
try
for i := Low(Properties) to High(Properties) do
begin
if not IsPublishedProp(SourceComp, Properties) then Continue;
if not IsPublishedProp(TargetComp, Properties) then continue;
if PropType(SourceComp, Properties) <> PropType(TargetComp, Properties) then
Continue;
case PropType(SourceComp, Properties) of
tkClass:
SetObjectProp(TargetComp, Properties, GetObjectProp(SourceComp, Properties));
tkMethod:
SetMethodProp(TargetComp, Properties, GetMethodProp(SourceComp,
Properties));
else
SetPropValue(TargetComp, Properties, GetPropValue(SourceComp, Properties));
end;
end;
except
Result := False;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
CloneProperty(Button1, Button2, ['Left', 'Font', 'PopupMenu', 'OnClick']);
ShowMessage('OK');
end;
 
去下个
quickrtti
那儿有源代码的,不过它是通过XML文件来实现的。
 
原来有SetObjectProp这个函数,我怎么不早一点知道呢?呵呵!谢谢Kingron和cqbaobao。
 
后退
顶部