Showing TFrame descendant's additional properties on the object inspector

浪尽此生 提交于 2019-11-29 02:01:43

Which custom module class are you registering for your frame? Which version of Delphi are you using?

From my experiments with Delphi 2007, the custom module class which seems to work is TFrameModule. This class is contained in delphivclide100.bpl. Since there is no corresponding delphivclide.dcp you have to load it manually:

unit FrameTestReg;

interface

procedure Register;

implementation

uses
  Windows, DesignIntf,
  FrameTest;

procedure Register;
var
  delphivclide: THandle;
  TFrameModule: TCustomModuleClass;
begin
  delphivclide := GetModuleHandle('delphivclide100.bpl');
  if delphivclide <> 0 then
  begin
    TFrameModule := GetProcAddress(delphivclide, '@Vclformcontainer@TFrameModule@');
    if Assigned(TFrameModule) then
      RegisterCustomModule(TTestFrame, TFrameModule);
  end;
end;

end.

My FrameTest unit is very simple, it has no FrameTest.dfm, only the declaration of the new TFrame descendant:

unit FrameTest;

interface

uses
  Forms;

type
  TTestFrame = class(TFrame)
  private
    FHello: string;
  published
    property Hello: string read FHello write FHello;
  end;

implementation

end.

Using TFrameModule class, everything seems to work fine so far. I can create a new descendant of TTestFrame to include in the project and edit its published properties in the Object Inspector, put instances of this new descendant on a form in the IDE, edit their new published properties in the Object Inspector, write event handlers for their child components etc. In the .dfm resource I can see the expected "inline" directive for the instances. I haven't encountered any problem with it so far so perhaps this is the solution.

There is no need to do in "hack way"

uses
...
  DMForm,
  VCLFormContainer,
...

procedure Register;
begin
...
  RegisterCustomModule(TYourFrameClass, TFrameModule);   // for frames
  RegisterCustomModule(TYourModuleClass, TDataModuleCustomModule);   // for data modules
...
end;

There is another way around to add frames too

type
  TNestableWinControlCustomModule = class (TWinControlCustomModule)
  public
    function Nestable: Boolean; override;
  end;

function TNestableWinControlCustomModule.Nestable: Boolean;
begin
  Result := True;
end;

+

  RegisterCustomModule(TYourFrameClass, TNestableWinControlCustomModule);

Names of units (tested in XE7):

TCustomModule => DesignEditors

TDataModuleCustomModule => DMForm (designide.dcp)

TWinControlCustomModule => WCtlForm (designide.dcp)

TFrameModule => VCLFormContainer (vcldesigner.dcp)

I suppose that for FireMonkey it should be possible in similar way (find fmxdesigner.dcp & check what is inside in Notepad++)

PS. In older Delphi versions there was TDataModuleDesignerCustomModule metaclass instead of TDataModuleCustomModule in unit DMDesigner

PPS. Other existing metaclass names:

TCustomFormCustomModule

TIDESourceModuleCustomModule

No, I don't think this is fully possible.

What I usually do when I have similar needs is to simply install the frame descendant as a component of its own right. But yes, that way you lose a lot of the typical frame behaviour (especially at designtime), e.g. you can no longer manipulate sub-components directly and changes to the frame do no longer automatically propagate to forms that use it at designtime - you have to recompile the runtime package that contains the frame first.

Then again, from an OOP-perspective this isn't too bad. It actually enforces the concept of implementation hiding. You can still expose individual properties and functionality of sub-components via new properties and methods on the frame itself.

boojum
procedure TMyFrame.Setstr(const Value: string);
begin
  inherited;
  Edit1.Text := Fstr;
  // Sadly this code won't work and Edit1 won't be updated in designtime.
end;

I think it's because it should not work at design time. You registered TBaseFrame as a custom module, so it is the TBaseFrame's (not it's descendants!!!) properties which should be editable at design time. Delphi IDE knows only about published properties of the class you've registered; it doesn't know anything about any descendants and overrides you've made in your project. To make the code work at design time, you should either include it in the TBaseFrame definition:

procedure TBASEFrame.Setstr(const Value: string);
begin
  inherited;
  Edit1.Text := Fstr; 
end;

or (in addition to TBaseFrame) register the TMyFrame definition as a custom module.

Try to understand: Delphi IDE at design time knows only about things that have been registered in it. It's not a handicap; it's logical behaviour.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!