在Delphi 6中为动态创建的VCL组件实例显式调用Loaded方法的替代
我有几个自定义VCL组件,它们在重写TComponent Loaded()方法时执行重要任务.这在动态创建实例时会产生麻烦,因为在运行时Delphi全局加载器不会调用Loaded()方法,就像在设计时放置在窗体/框架上的组件一样.我还必须将Loaded覆盖放在类声明的公共部分中,因此无论创建组件实例的代码都可以调用它.最后,我必须记住为动态创建的实例调用Loaded(),否则细微的bug会蔓延到应用程序中,这个问题已经让我好几次了.
有更好的解决方案或方法吗? 解决方法
如果你需要在你的代码中调用Loaded你做错了.如果你依赖第三方控制,那么我会修复那个人的控制权.请参阅下文.
让我举一个假设的例子:假设我有5个已发布的属性,一旦它们全部被加载,可以生成复杂的曲线甚至更好,生成分形,这需要很长时间. 在设计时我想在加载后立即预览此曲线,但我不希望在DFM流式传输期间重新计算曲线5次,因为每个参数P1到P5(类型为Double)都有一个SetP1方法,它调用一个受保护的方法名为Changed,并重建我的曲线.相反,如果csDesigning或csLoading处于组件状态,我会返回SetP1方法,然后我从Loaded调用一次Changed.显然,在所有情况下,我都不能单独依赖属性设置器方法来调用所有更改.所以我需要Loaded告诉我做第一代一些昂贵的工作,我想要完成一次,而不是N次,其中N是已经加载的具有方法设置过程的DFM属性的数量调用名为Changed的方法或类似的方法. 在您的情况下,在运行时,您根本不应该依赖于Loaded被调用.相反,您应该将属性集方法调用Changed.如果你需要某种方法一次更改多个属性,然后只做一次昂贵的事情,那么实现TMyComponent.BeginUpdate / TMyComponent.EndUpdate类型的方法调用,并避免额外的工作. 我认为没有任何有用的地方,从Loaded做一些事情是有意义的,除了上面的情况,这应该是特定于设计时和基于DFM的类使用.我希望正确设计的TComponent或TControl只需通过在代码中创建并通过设置其属性来正确初始化自身. 因此,对于我假设的TMyFractal组件,我会在代码中创建它时执行此操作,而无需使用DFM加载或调用Loaded: cs := TMyFractal.Create(Self); cs.Parent := Self; {Parent to a form} cs.Align := alClient; cs.BeginUpdate; cs.P1 := 1.03; // does NOT trigger Regenerate cs.P2 := 2.3; cs.P3 := 2.4; cs.P4 := 2.5; cs.EndUpdate; // triggers expensive Regenerate method . cs.Show; // later someone wants to tweak only one parameter and I don't want to make them // call regenerate: cs.P5 := 3.0; // Each param change regenerates the whole curve when not loading or in a beginupdate block. 在我的TMyFractal.Change方法中,我会调用昂贵的RegenerateCurve方法一次,每次在运行时修改任何系数P1-P4,在初始设置之后,并且恰好在组件从DFM流入时,其中Loaded仅用于处理我很难指望在我的控件中执行beginupdate / endupdate的事实,就像我在上面的代码中所做的那样. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |