[Lazarus] TFrame improvements

Martin Frb lazarus at mfriebe.de
Mon Nov 29 12:05:37 CET 2021

On 29/11/2021 11:36, Michael Van Canneyt wrote:
> On Mon, 29 Nov 2021, Martin Frb via lazarus wrote:
>> On 29/11/2021 10:52, Juha Manninen via lazarus wrote:
>>> Please everybody test issue:
>>> https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/25124
>>> Some components caused an error when placed on a Frame. Now it 
>>> apparently works.
>>> Can somebody please explain why it works. (See my comment there).
>> From reading the issue, and a peak at the code:
>> - When the frame is read from stream, the property is triggered, as 
>> it should (and as on a Form.
>> - The property accesses "canvas" => that triggers asking for a handle 
>> (which is created based on CreateParams)
>> A form does not need a parent (it can have one, if it is embedded).
>> Therefore CreateParam for TForm checks this and removes flags such as 
>> WS_CHILD (not sure if WS_TABSTOP would cause an issue, but it makes 
>> no sense...)
>> A frame, at least at design time, can display without parent too. (I 
>> guess: it acts as if it is a TForm in that case).
>> => So for that IMHO your patch is correct (for design time).
>> Yet a TFrame at runtime IMHO should always have a parent.
>> No idea, if there is other code, that relies on that....
>> So maybe your patch should be extended, to only do that, if the 
>> control is in "designtime" state?
>> Though, not sure if it is worth it. While it would be correct to fail 
>> at runtime if there is no parent, it would not bring any benefit. If 
>> other code in TFrame needs the parent, then it will fail in the other 
>> code, if not then it will work.
>> The question is, do we commit to it may work, and then maybe have to 
>> fix more later? Otherwise it may want to even throw an exception, if 
>> it does not have a parent at runtime?
> I often create a frame in code (so no parent) which is then placed on 
> a form.
> Will this scenario still work ?

Well, if your code works now, then apparently it does not access the 
handle/canvas before setting a parent?
Which also means, you do not "show" the frame, before it has a parent.

With Juha's current patch: Yes. => Afaik this adds no restrictions.
=> Except, if you are waiting for an Exception, because you expect it to 
fail. ;)

If we add a "if designtime" around Juhas code, still nothing changes for 
your code. Since then runtime behaviour would be exactly as it currently is.

If we add
    If (not designtime) and (ParentWindow = nil) then raise Exception();
afaik still nothing changes (except for the error message).
Because currently, without Parent/ParentWindow it will fail to create 
the Handle (Actually, may need to be tested for all WidgetSets).

If your code creates a Frame that during its creation (reading from lfm, 
or calls by other code) triggers any component to access the canvas, or 
otherwise needing a handle,
then your code would fail already (without Juha's Patch).

With the current Patch, such an "canvas" access would create a handle 
(it might not make it visible, but it could even do that).
If that handle is created, and you set a Parent, then the handle would 
have to be discarded.

So unless a frame should be able to be visible shown at runtime as if it 
was a Form of itself, any handle created without parent is created to be 
discarded again.
Such a handle would only serve the purpose to allow incorrect code to 
"get away" (I.e. to draw text on an invisible canvas, that will never 
become visible).

Question is:
- Should that be allowed?
- Should components access the canvas in "csLoading", or "if not 
HandleCreated"  (unless they indent for the Handle to be created at that 
time, and therefore are aware if that is possible)

More information about the lazarus mailing list