我定制了一个控件(TMyComponent),它会关联n个其他控件。并保存每个控件的信息(通过自定义的TMyControls类)。但是当某个被关联(记录信息)的控件更改名字的时候,我该如何处理呢?或者说,我要怎么得知某个已经被我记录了信息的控件更名的通知?
解决方案 »
- 一个很基础的语法问题?请大家给解释一下!
- 已经做好的窗口 想继承另个窗口的一些属性和功能 怎么做?
- 想写一个有运算的SELECT语句在DBGRID里显示出来
- borland delphi7.0又没有类似vc的visual assist x 提示工具插件???
- 如何取得Tradiogroup控件中的值
- 在连接数据库查询时出现access violation
- access下,为什么执行adoquery1.insert后,所增加的记录是在数据库的最后呢?(在线等待)
- socket传送数据的问题?
- MP3Class.pas(46): Symbol '_DMp3Play' is specific to a platform 这是什么错误!!怎么解决,请进
- 如何使窗体的最大化按钮成灰色?
- 请问怎么在Treeview中给节点加上Checkbox?
- dataset问题?请求各位帮忙
begin
if FName <> NewName then
begin
if (NewName <> '') and not IsValidIdent(NewName) then
raise EComponentError.CreateResFmt(@SInvalidName, [NewName]);
if FOwner <> nil then
FOwner.ValidateRename(Self, FName, NewName)
//可以看到当每一个组件更新时候,会对他的拥有者发消息
//可以在拥有者的ValidateRename消息
else
ValidateRename(nil, FName, NewName);
SetReference(False);
ChangeName(NewName);
SetReference(True);
end;
end;procedure TComponent.ValidateRename(AComponent: TComponent;
const CurName, NewName: string);
begin
if (AComponent <> nil) and not SameText(CurName, NewName) and
(AComponent.Owner = Self) and (FindComponent(NewName) <> nil) then
raise EComponentError.CreateResFmt(@SDuplicateName, [NewName]);
if (csDesigning in ComponentState) and (Owner <> nil) then
Owner.ValidateRename(AComponent, CurName, NewName);
end;
在看在类中ValidateRename为虚方法!
TComponent = class(TPersistent, IInterface, IInterfaceComponentReference)
protected
procedure ValidateRename(AComponent: TComponent;
const CurName, NewName: string); virtual;
end
所以我的想法是做一个TFROM的子类对上面的虚函数进行OVERRIDE
然后在消息发生时候发消息通知你做的组件
procedure ValidateRename(AComponent: TComponent;
const CurName, NewName: string); override;
//在TFORM类的父类中你可以发现他被覆盖了procedure TCustomForm.ValidateRename(AComponent: TComponent; const CurName,
NewName: string);
//覆盖后的代码
begin
inherited ValidateRename(AComponent, CurName, NewName);
if FDesignerHook <> nil then
FDesignerHook.ValidateRename(AComponent, CurName, NewName);
end;所以我的方法你明白了把就是做一个TFORM的子类,
然后对ValidateRename进行覆盖,
然后用这个你做的类,做那些控件的父窗口并且做成拥有者形式,就是那些控件如果动态生成的话,要把拥有者参数写成你生成类的窗口啊。花我20分钟看VCL
但是很不幸的是,如果“n个其他控件”的拥有者为nil的话,这样就无法解决问题了。—————————————————————————————————
宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。
—————————————————————————————————
procedure SetName(const NewName: TComponentName); virtual;
对于单个的组件,可以覆盖这个方法,就可以得到名字修改信息。但是对于多个组件,显然不能一一覆盖,如果能找到动态创建函数和过程的方法(就是动态创建新的SetName方法用来替换原来的SetName),这个问题就解决了。可惜我最近一直为这个问题烦恼,不知道怎么办呢。—————————————————————————————————
宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。
—————————————————————————————————
lxpbuaa(桂枝香在故国晚秋) :
我想对于组件来说他们的SETNAME的函数所在VMT的索引号是相同的,但是索引号下的调用地址可以不同因为是VIRTUAL函数,所以我的想法可以直接修改该索引下的调用地址,指向我们新做的一个SETNAME中去,做完以后也可以链接原来的旧的SETNAME,形成一个调用莲,这就可以动态连接拉!
不过第一我可不打算写一个tform子类,因为这样通用性(姑且先这么说)不强。
还有那部分vcl源码我也看了,setname只是向owner传递更名的通知。
至于“修改该索引下的调用地址”应该也可以在设计期完成,不过我觉得这样做也有点得不偿失。
不知道大家还有没有新的发现呢?
另外zhboy(孔方兄) 说保存这些控件的指针倒是可以考虑......我自己再试试看吧。
再次谢谢大家,这点分不够我可以再开一个帖子。
取得SetName的地址可以通过RTTI搞定(具体的就是通过GetPropInfo(,'Name'),然后给SetName加上一个偏移就可以)。但是SetName是一个方法而不是过程,方法有一个附加的对象指针(指向所属对象),在动态创建此方法时,如果指定此对象指针,是一个难题。—————————————————————————————————
宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。
—————————————————————————————————