4
votes

Having a situation: two packages: "Base" and "Descendant" and an application "Example". The Base package and the Example application may be in one project group, but the Descendant package has to be in other project group, without any source code of Base and Example.

The aim of such manipulation is to hide Base and Application sources from workers who will work with Descendant package.

Base package contains a form: TFormBase with some components and some code. I build it and get some binary files: bpl, dcp, etc...

type
  TFormBase = class(TForm)
    Panel1: TPanel;
    BOk: TButton;
    BCancel: TButton;
    procedure BOkClick(Sender: TObject);
    procedure BCancelClick(Sender: TObject);
  private
  protected
    function GetOkButtonCaption: string; virtual;
    function GetCancelButtonCaption: string; virtual;
  public
  end;

implementation

{$R *.dfm}


procedure TFormBase.BCancelClick(Sender: TObject);
begin
  ShowMessage('"' + GetCancelButtonCaption + '" button has been pressed');
end;

procedure TFormBase.BOkClick(Sender: TObject);
begin
  ShowMessage('"' + GetOkButtonCaption + '" button has been pressed');
end;

function TFormBase.GetCancelButtonCaption: string;
begin
  Result := 'Cancel';
end;

function TFormBase.GetOkButtonCaption: string;
begin
  Result := 'Ok';
end;

Descendant package contains TFormDescendant = class(TFormBase)

type
  TFormDescendant = class(TFormBase)
  private
  protected
    function GetOkButtonCaption: string; override;
    function GetCancelButtonCaption: string; override;
  public
  end;

implementation

{$R *.dfm}


function TFormDescendant.GetCancelButtonCaption: string;
begin
  Result := 'Descendant Cancel';
end;

function TFormDescendant.GetOkButtonCaption: string;
begin
  Result := 'Descendant Ok';
end;

And code of Descendant.dfm:

inherited FormDescendant: TFormDescendant
  Caption = 'FormDescendant'
end

Descendant.dpr:

requires
  rtl,
  vcl,
  Base;

contains
  Descendant in 'Descendant.pas' {FormDescendant};

When creating FormDescendant it should look like FormBase because it is simply inherited from it. And we can add some other components on this FormDescendant saving FormBase look.

But when we try to open FormDescendant in Delphi IDE, it crashes with "Error creating form: Ancestor for 'TFormBase' not found." And that's right: Base.bpl contains only binary code and Delphi doesn't know how TBaseForm looks in design-time.

What should I do to open FormDescendant in Delphi?

I've read How do I use or resolve issues with visual form inheritance in Delphi? and Register custom form so I can inherit from it from multiple projects, without copying the form to the Object Repository folder But those advices didn't help. Is there a way to open FormDescendant in design-time without sources of TFormBase?


Here're the projects of the example for experiments: http://yadi.sk/d/IHT9I4pm1iSOn

1
It seems that IDE needs the sources of TFormBase. But why should it be not accessible to some workers? No change of code -> store them in a read-only dir (even with a VCS). Should not see the "top secret" code? - Why do you have "top secret" code inside your forms. You should extract this part into a seperated unit and just hand over the .dcu filesSir Rufo
@SirRufo yes, IDE needs FormBase.dfm sources. But the FormBase.dfm is in another SVN server, where the workers don't have an access. Now, we give a copy of Base package to workers. There is no "top secret" code :) As you have mentioned, such code should be stored in other runtime packages without forms. And it is. But I'd like to give to them only *.bpl files... That's the question...Mikhail Kopylov

1 Answers

1
votes

You can provide a stub unit with (some of the) implementation code stripped, only the .dfm and interface has to be identical. This is what Allen Bauer did for his Opening Doors article showing how to implement dockable IDE forms.

Your developers will then need to first open the stub form unit and then they will be able to open the descendant form.