Jump to content
dmitrybv

Does FMX designer support frame inheritance?

Recommended Posts

If a FMX Frame is created from a class that is a descendant of the TFrame class, the designer starts saving non-existent properties in the fmx file.
For example, in my project, a frame saves the ClientHeight and ClientWidth properties in the file, although there are no such properties in the TFrame class.
As a result, when trying to place a frame on a form, an error occurs: ‘Cannot paste a from or datamodule into another form or module’.
When trying to create a Frame at run-time, an error occurs: Project Project1.exe raised exception class EReadError with message 'Property ClientHeight does not exist'.
I attach screenshots and a demo project.


 

unit UnitBaseFrame;

interface

uses SysUtils, System.Classes, System.StartUpCopy,
     FMX.Forms, FMX.TabControl;

type

{ TBaseInTabFrame }

  TBaseInTabFrame = class(TFrame)
  private
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

implementation

{ TBaseInTabFrame }

constructor TBaseInTabFrame.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
end;

destructor TBaseInTabFrame.Destroy;
begin
  inherited Destroy;
end;

end.

 

 

unit UnitInheritedFrame;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  UnitBaseFrame,
  FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls;

type
  TInheritedFrame = class(TBaseInTabFrame)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

implementation

{$R *.fmx}

end.

 

object InheritedFrame: TInheritedFrame
  Left = 0
  Top = 0
  ClientHeight = 480
  ClientWidth = 640
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop, iPhone, iPad]
  DesignerMasterStyle = 0
end

 

sshot-359.png

sshot-358.png

2024-08-26-FrameInheriting.zip

Share this post


Link to post
Posted (edited)

Your fmx file is wrong:

 

26 minutes ago, dmitrybv said:

 


object InheritedFrame: TInheritedFrame
  Left = 0
  Top = 0
  ClientHeight = 480
  ClientWidth = 640
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop, iPhone, iPad]
  DesignerMasterStyle = 0
end

 

In the first line, it should be inherited instead of object. If it's inherited, it draws all the properties from the parent classes, but if it's an object, it won't inherit anything. I never investigated why it saves those properties, which are properties from TForm and not TFrame ones.

 

Edit: to properly inherit an existing frame in the same project, right click the project in the Projects view, Add new > Other > Delphi (drop down in new window) > Inheritable Items. There you'll see your frames, and you'll only be able to Inherit them (other options Copy and Use will be disabled).

Edited by havrlisan
Added how to inherit

Share this post


Link to post

1. This file was created by RAD Studio designer. I did not modify it manually.
2. Why do I need inherited here if the base class - TBaseInTabFrame does not have an fmx file?
3. I created a new frame TInheritedFrame, then in the unit file UnitInheritedFrame, I changed the line TInheritedFrame = class(TFrame) to TInheritedFrame = class(TBaseInTabFrame), because I need to have several basic methods for all frames of my project in the base class TBaseInTabFrame.

Share this post


Link to post
6 minutes ago, dmitrybv said:

1. This file was created by RAD Studio designer. I did not modify it manually.
2. Why do I need inherited here if the base class - TBaseInTabFrame does not have an fmx file?
3. I created a new frame TInheritedFrame, then in the unit file UnitInheritedFrame, I changed the line TInheritedFrame = class(TFrame) to TInheritedFrame = class(TBaseInTabFrame), because I need to have several basic methods for all frames of my project in the base class TBaseInTabFrame.

1. Correct, and RAD Studio correctly created the fmx file. However, you changed your class inheritance from TFrame to TBaseInTabFrame, and because of that the correct keyword becomes inherited, not object. RAD Studio cannot know what your intentions are, so you must change it manually.

2. Your TBaseInTabFrame should have an fmx file; that's how I've always done it. I suppose you just created a blank unit and declared it, but you should create the unit as a new FireMonkey Frame (that's an actual option in the Add New tab menu). That way frame inheritance will work properly.

3. Read the previous two statements, they explain why that's a wrong approach.

Share this post


Link to post

Yes, you are right.


Changing the line
 

object InheritedFrame: TInheritedFrame


to
 

  inherited InheritedFrame: TInheritedFrame


fixes the problem with the ClientHeight, ClientWidth properties in the fmx file.

 

That is, Frames only support visual inheritance.

 

Although for a Form, if there is no fmx file in the base form, it is not necessary to use inherited.

Share this post


Link to post

I would recommend not to use frames visually in the IDE, but only insert them at runtime.
That will prevent a lot of issues in the IDE designer.
Of course you can edit the frame itself, like with any other form.
But using this frame in the designer on another form requires the designer to handle everything properly,
which is still quite fragile during development.

Using in runtime only doesn't affect the designer and the IDE will stay much more stable.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×