The basic problem you have is that the child forms do not have any knowledge of the main form and so cannot access it. In fact, that's not really a problem in my view. That's good design and sound encapsulation. In an ideal world, the child forms should be able to be hosted anywhere.
So what you need is a way for the children to obtain information that their host provides. Since you don't want the children to know anything about the implementation of their host, this naturally leads towards using an interface.
So, decide what information the host needs to be able to supply to the children. For example:
type
IAppProps = interface
[...] // add a GUID here
function GetUserName: string;
property UserName: string read GetUserName;
... // more properties and/or methods as appropriate
end;
You can implement this readily in your main form, or indeed some other class in your host application:
type
TMainForm = class(TForm, IAppProps)
...
function GetUserName: string;
...
end;
Next you need for your children to be able to receive an IAppProps
interface reference.
type
TBaseChildForm = class(TForm)
private
FAppProps: IAppProps;
public
property AppProps: IAppProps read FIAppProps write FIAppProps;
end;
Then when your host creates a child form it simply writes:
ChildForm.AppProps := Self;
And it's all good.