I'm using RAD Studio XE5 to build my application.
I saw that is was not very practical to try tu publish properties on a TForm. It then has to be registered and installed as a package, then it's not practical for heavy development.
So, I decided I would create a non visual component (TFormPropertiesEditor) that would be used to fill up form properties. A way of standardising my forms.
The component would be dropped on the base form, a form of which every other form inherits (let's call it TBaseForm). So, the component would be dropped only once on the 'base' form, then with inheritance, every other form would have it too.
The created component would detect the class of its Owner (BaseForm or its descendents) and create an object accessible through the 'Properties' property, whose class would be conditional to the owner class.
This way, when inspecting the component on a TBaseForm, I would have access to the TBaseFormProperties only. When inspecting the component on a TSecondForm, I would also have access to the TSecondFormProperties. Only, the component would be intelligent enough to detect which PropertyClass it should expose as the Properties property.
The component would inspect the form, through the GetPropertiesClass, defined as :
function TBaseForm.GetPropertiesClass : TPropertiesClass;
begin
Result := TBaseFormProperties;
end;
function TSecondForm.GetPropertiesClass : TPropertiesClass;
begin
Result := TSecondFormProperties;
end;
Each form has a corresponding TProperties descendent, like so :
TBaseForm ------------ TSecondForm ------------- ...
|
TBaseFormProperties -- TSecondFormProperties --- ...
For example :
If the Form on which the component is placed is TBaseForm, FProperties would be a TBaseFormProperties. If the form is a TSecondForm, FProperties would be TSecondFormProperties. Naturally, TSecondFormProperties would inherit from TBaseFormProperties.
Though, when I place the component on the form, it seems to be unable to detect of which class the component is.
function TFormPropertiesEditor.GetPropertiesClass: TFormPropertiesClass;
begin
Result := TBaseForm(Owner).GetPropertiesClass;
end;
It looks like the TBaseForm(Owner) part is causing the problem. The interpreter is stuck on the TBaseForm, and will not consider if Owner is of type TSecondForm or TThirdForm.
Interfaces
So, to get around the TBaseForm(Owner) typecasting, I decided to use an interface. So if I use an interface that declares the GetPropertiesClass:
IMasterForm = interface(IInterface)
['{B6122F34-65C4-4701-8A5E-50C8DABF5516}']
function GetPropertiesClass : TFormPropertiesClass;
end;
type
TBaseForm = class(TForm, IMasterForm)
MyFormPropertiesEditor1: TMyFormPropertiesEditor;
private
{ Déclarations privées }
public
function GetPropertiesClass : UCommon.TFormPropertiesClass;
end;
The following :
function TFormPropertiesEditor.GetPropertiesClass : TFormPropertiesClass;
begin
Result := (Owner as IMasterForm).GetPropertiesClass;
end;
Results into an Interface not supported error.
Abstract Ancestor Method
Then, I decided to add an extra layer of ancestry. I've added a class, TMasterForm, from which TBaseForm inherits. This TMasterForm declares GetPropertiesClass as abstract and virtual :
TMasterForm = class(TForm, IMasterForm)
public
function GetPropertiesClass : TFormPropertiesClass; virtual; abstract;
end;
type
TBaseForm = class(TMasterForm)
private
{ Déclarations privées }
public
function GetPropertiesClass : UCommon.TFormPropertiesClass; override;
end;
But then, I get an AV because I think the IDE tries to access TMasterClass.GetPropertiesClass, which is of course not implemented.
How can this TypeCasting be accomplished? Any idea how could I proceed ?
Thank you very much in advance
Download Sample Project https://www.wetransfer.com/downloads/b524438609fc04257af803a8e3dd2eca20141225161239/764d108d335b9d296c3004dfea04a54620141225161240/9c8cc0
The basic problem here is that the IDE does not instantiate your form at designtime. So, no matter what code you put in the form class, it won't be executed by the IDE. This is because you did not register the form with the IDE.
If you wish the IDE to have knowledge of your forms then you need to register them with the IDE. And at that point all your code becomes needless because you are back to doing what you are attempting to avoid. Namely registering the forms with the IDE. You are stuck in a Catch 22 situation. If you need the IDE to know about the forms then you need to register them. At which point you may as well just surface the properties directly in the Object Inspector.