Alternatively call Loaded method explicitly for dynamically created VCL component instances in Delphi 6?

I have several custom VCL components that perform important tasks in overriding the TComponent Loaded () method. This interferes with creating instances dynamically, since the Loaded () method is not called by the global Delphi loader at runtime, as well as for components that were placed on forms / frames at design time. I also have to put the Loaded override in the public section of the class declaration so that any code that creates an instance of the component can call it. Finally, I have to remember that you are calling Loaded () for dynamically created instances, or subtle errors will creep into the application, a problem that has already hit me a bit.

Is there a better solution or approach to this?

+4
source share
1 answer

If you need to call Loaded in your code, you are doing it wrong. If you depend on a third-party control that does this, I would fix this control. The following shows how.

Let me make a hypothetical example: suppose I had 5 published properties that, when they are all loaded, can generate a complex curve, or even better, generate a fractal, which takes a lot of time.

At the time of design, I want to look at this curve as soon as it is loaded, but I do not want the curve to be recalculated 5 times during DFM streaming, since each parameter P1-P5 (Double type) has a SetP1 method that calls the protected method called "Modified" and rebuilds my curve. Instead, I have a SetP1 return method if csDesigning or csLoading are in component states, and then I call Changed once from Loaded. Clearly, I cannot rely solely on property setting methods, in all cases, to cause all changes. Therefore, I need to download Loaded to tell me to do my first generation of some expensive work, that I want to do 1 time for sure, and not N times, where N is the number of DFM properties that would be loaded, which had a set of methods that were called a method called Modified or something like that.

In your case, at runtime you should not rely on Loaded get invoked at all. You should be instead if your property set methods cause a change. If you need to somehow change several properties at once, and then do several expensive things only once, then implement the type of the method call TMyComponent.BeginUpdate / TMyComponent.EndUpdate and avoid additional work.

I can think of NO useful places where doing something with Loaded makes sense, except in cases like the above, which should be specific for use in DFM-based design and use. I would expect a properly designed TComponent or TControl to initialize properly by simply creating it in the code and setting its properties.

So, for my hypothetical TMyFractal component, I would do this when creating it in code without using a DFM load or calling 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. 

In my TMyFractal.Change method, I will refer to the expensive RegenerateCurve method once, every time any P1-P4 coefficient is changed at runtime, after the initial setup, and once when the component is transferred from DFM, where Loaded is only used in order to cope with the fact that I can hardly expect that in my control I will do startupdate / endupdate, as it would in the code above.

+3
source

Source: https://habr.com/ru/post/1398311/


All Articles