如何读取或修改未知(任意)类的一个instance中某项property的值?(50分)

  • 主题发起人 Another_eYes
  • 开始时间
A

Another_eYes

Unregistered / Unconfirmed
GUEST, unregistred user!
我知道用GetPropInfo可以判断一个component中是否包含某项属性.
但是如果通过GetPropInfo函数得到了该属性的propinfo指针, 如何
读取或修改该属性的值?

如果已答问题中有答案, 也麻烦您贴过来.
这么慢的网, 实在没时间反复重试去load已答问题
 
1.读取属性:

设Info为PPropInfo;

Info^.Name为属性名称 e.g. Caption, Color ...

case Info^.PropType^.Kind of可以检测属性类型,有
tkInteger,tkString,tkLString,tkEnumeration,tkClass,tkSet等

例如对tkString,tkLString
用PropValue:=GetStrProp(Component, Info);可以得到属性字符值.

对tkEnumeration
用OrdValue:=GetOrdProp(Component, Info); //获得Int值
PropValue:=GetEnumName(Info.PropType^, OrdValue); //转为str
可以得到枚举属性字符值.

...

2.设置属性:
用属性的PropertyEditor.SetValue(Value: string)或者
用属性的PropertyEditor.Edit;

需要调用GetComponentProperties,在其中设置回调函数以取得
属性的PropertyEditor

研究一下 <a href=/delphi/attachments/handel.zip>handel.zip</a> 吧 :)
 
运行时, 能用PropertyEditor设置值吗?
 
其实我的问题很有现实意义的. 运行时经常会碰到需要修改一批控件的某个相同属性
值的问题. 难道一定要用case 或if else一个一个判断这些控件的所属类再用
相关类.属性:= 进行修改吗? 举个很普通的例子:
屏幕上有TLabel, TEdit, TCombobox, TButton, 这些类都有Font属性, 但是这
些类的相同父类只有TWinControl. 而TWinControl不存在Font属性.
难道要同时修改这些类的font只能
if Control is TLabel then (Control as TLabel).Font.Assign(AFont)
else if Control is TEdit then....
else if Control is ....
....
吗?

我想, propinfo既然可以读属性的值, 也应该可以修改它.

不知道delphi自己是怎么做的(它自带的可是500多个类啊).

请各位大侠伸个小指头帮一帮吧. 我想很多人都希望知道这个方法的.
(不想知道的请举手)
 
现成的属性编辑器控件很多, 仿Delphi的PropertyInspecter, 运行时修改属性
 
原理呢?
 
TStringGrid+TPropInfo
 
我推荐的就是著名的 Delphi by Delphi: <a href=/delphi/attachments/handel.zip>handel.zip</a>.
我自己修改它就得到了一个不错的 Runtime Property Editor.

huizhang,现成的属性编辑器控件,能给参考参考吗?
 
就我所知,比较好的现成的属性编辑器控件,
没有一个是免费公开源码的。
谁去买一个,然后公开出来,可就造福人民了,呵呵。
 
老孙, DbyD的却不错, 但是属性编辑器不能直接使用, 必须与TFormDesigner(D3)
or IFormDesigner(D4)同时使用才行; 要想替掉 FormDesigner 要做很多工作
 
huizhang,您说得极为正确,为此问题我研究了一整天,
最后怎么解决的呢?相当简单:继承一下TFormDesigner就完了.

TMyDesigner=class(TFormDesigner)
procedure Modified; override;
end;

procedure TMyDesigner.Modified;
begin
end;

MyDesigner: TMyDesigner;

然后用GetComponentProperties就畅通无阻了

MyDesigner := TMyDesigner.Create;
GetComponentProperties(CompList, tkProperties, MyDesigner, GetPropEditor);
 
各位, 也许我没说清楚. 我的要求并不是写个运行时的object inspector.
我只希望能在程序里修改不特定类的特定属性(不要用户的参与). 比如Text属性.
(对程序运行半当中初始化一大批控件很有用), 难道这样也需要继承TDesigner和TProprtyEditor 让用户来修改吗?
 
这不是指RTTI的应用吗?一开始我也以为...
我有一个例子(从网上搞来的),相当完整的一个过程组,
给你发过去好了.
 
这不是指RTTI的应用吗?一开始我也以为...
我有一个例子(从网上搞来的),相当完整的一个过程组,
给你发过去好了.
 
邮件已寄出.

唉!好久没犯连按两次的错误了 :)
 
Another_eYes:

你的问题似乎是想同时改变一批控件的相同属性.在这种情况下,一般都是其
公共父类的属性,只是在父类中为保护类型,未Publish.因此我们可以变通一下.
如:
TMyClass=class(TControl);

...

procedure Form1.ChangeFont;
var i : integer;
begin
for i:=0 to controlcount-1 do
begin
TMyClass(Controls).Font.color := clred;
....
end;
end;

因Delphi的公有/私有/保护,是相对单元而言的,所以我们可以通过
继承类对其进行访问.

但愿对你有用,只是有点晚了!本人昨天才注册的.hehe!
 
Hi, Another_eYes:

我寄出去的程序应该没问题吧!
如果不是你想要的,也请说明一下.
 
多谢DSP的解答.
但是您的方法实用性上有很大限制(抱歉这么说)
举个简单的例子:
TEdit和TListBox都有BorderStyle属性.
但是它们的父类只有到TWinControl这一级才相同, 而自TWinControl以上各类都
没有BorderStyle属性.
我记得Delphi是只允许继承自一个父类的(和JAVA相似), 因此如果要修改BorderStyle
属性就不得不用两个类. 相似的情况还很多...
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
顶部