0

I have this bug in delphi i'm inherating from different forms (3 in total) and when i'm creating the last child, it creates every component 3 times. It's dll project and the dll makes the different forms. I have a launcher for testing that dll. On calling the function that creates the form needed it creates all 3 of them in one window (screen below). I have tried giving my components the same name. It doesn't show any errors on compiling the dll but on calling the function from the launcher it says that this or that component already exists, so i had to give all my components different names. (If it's not clear please ask me questions i don't know how to explain it more clearly)

Here are my form definitions:

  TFrmReserve007 = class(TfrmRsrvExtended)
  private
    { Private declarations }
    [...]
  protected
    { Protected declarations }
    [...]
  public
    { Public declarations }
    [...]
  end;

TfrmRsrvExtended = class(TfrmRsrv)
    Act_Browse2: TAction;
    Act_SaveAs2: TAction;
    Act_LoadDefault2: TAction;
    ImageListToolbar2: TImageList;
    PSCMandatoryObjects2: TPSCMandatoryObjects;
    ImageListMouvement2: TImageList;
    [...More components...]
    TopPanel2: TPSCTopPanel;
    procedure Act_BrowseExecute(Sender: TObject);
    procedure Act_LoadDefaultExecute(Sender: TObject);
    procedure Act_loadSenderExecute(Sender: TObject);
    procedure bbtn_Browse2Click(Sender: TObject);
  private
    { Private declarations }
    [...]
  protected
    [...]
  public
    { Public declarations }
    [...]
  end;

TFrmRsrv = class(TForm)
    PSCButtonPanel1: TPSCButtonPanel;
    PageControl: TPageControl;
    TabSheeta: TTabSheet;
    [.. More components...]
    Act_LoadKeyWord1: TAction;
    Act_LoadStorage1: TAction;
    Mandatory1: TPSCMandatoryObjects;
    PSCHint: TPSCHint;
    {$ENDREGION}
  private
    { Private declarations }
  protected
    { Protected declarations }
    [...]
  public
    { Public declarations }
    [...]
  end;

This [...] means there are functions and procedures there.

And here's the screen i have when calling the form creating with TFrmReserve007.Create(nil)

enter image description here

MCVE

LAUNCHER

procedure setLXCom;
begin
  if lxPom59Svc = nil then
  begin
    ClassID := ContractIDToClassID('pom59PumaToRio@dtad');
    IU := CreateLynxObject( ClassID);

    if IU = Nil then begin
      raise Exception.Create( 'CreateLynxObject failed');
    end;

    IU.QueryInterface( Ipom59Svc, lxPom59Svc);

    if lxPom59Svc = nil then
    begin
      raise Exception.Create( 'QueryInterface ILynxRio failed');
    end;
  end;
end;

procedure TForm1.Button11Click(Sender: TObject);
begin
  setLxCom;
  lxPom59Svc.RioSvcGui007V2(
  LxPom59Svc.RioGetDataPCE007V2('9051','2010010281',false),lgFRENCH)
end;

DLL

function tl_pom59Svc.RioSvcGui007V2(
  Info: IInfoNotisReservation;For007:boolean;Extension:string; ParentWindow: HWND)
  : IInfoNotisReservation;
var
   Ok : Boolean;
   untKey: String;
   canSave : Boolean;
begin
  Ok := False;
  GetRioDB(fRegister);
  untKey  :=  RioN.GetRegisterByID(RioN.RegisterID, FLAG_IGNORE_SECURITY).Data.UnitID.Value;
  canSave :=  RioN.GetPieceAccess(info.pieceID).Edit;

    While Not(Ok) do
      begin
        Ok := true;
        case LoadFRM_ReservationMod007(Info,
        fRegister, UntKey, canSave, For007, Extension,Parentwindow) of
          TR_Ok :
            begin
              Result := Info;
            end;
          TR_Cancel :
            begin
              Result := Nil;
            end;
          else
            Result := Nil;
        end;
      end;

end;

Function LoadFrm_ReservationMod007(var InfoReservation : IInfoNotisReservation;
               Reg_Key,Unt_Key:string;CanSave:Boolean;For007:boolean;Extension:string; ParentWindow: HWND):TTrilean;
var
  Frm_ReservMod007: TFrmReserve007;
begin

  Frm_ReservMod007 := TFrmReserve007.Create(nil);
  FRM_ReservMod007.ShowModal;    
  if Frm_ReservMod007.ModalResult <> Mrcancel then
      begin
        InfoReservation.Assign(Frm_ReservMod007.InfoReserv);
        Result := TR_Ok;
      end
    else
      begin
         InfoReservation := Nil;
         Result := TR_Cancel;
      end;

end;
Community
  • 1
  • 1
Mario R.
  • 91
  • 2
  • 11
  • 1
    It's really not at all clear what you are doing here. Can't we have an MCVE? And you should also clarify how the DLL and the host executable are related. If they are both VCL applications then your design won't ever work. You'd have two instance of the VCL, which is one too many. This is the reason why runtime packages exist. – David Heffernan Jun 08 '15 at 08:46
  • @DavidHeffernan No they are not both VCL Applicaitons. One is VCL the other one is a dll. i'm using com for that. My launcher just creates the link with the dll and calls the function that creates the form. The function it self it's just callse the .create(nil) nothing else. – Mario R. Jun 08 '15 at 08:54
  • If the DLL is coded in Delphi then you have two instance of the VCL. One in the host executable and one in the DLL. Whether or not that's a problem we cannot be sure from here since you didn't include enough detail. Likely it will be a problem. Please show an MCVE. – David Heffernan Jun 08 '15 at 08:55
  • What exactly do you want? Launche calls the function blabla() and the function blabla does form.create(nil). I didn't coded the create function, it's a delphi class... I don't get what exactly do you want from that htere's nothing more to show, it only does create that's all. It like showing a mcve of a ShowMEssage function... that only show a text, not even calling another function. Idk man – Mario R. Jun 08 '15 at 08:58
  • http://stackoverflow.com/help/mcve – David Heffernan Jun 08 '15 at 09:00
  • @DavidHeffernan I've edited with the MCVE tell me if it's more clear – Mario R. Jun 08 '15 at 09:07
  • @DavidHeffernan Any idea? My forms doesn't have a constructor. The .Create(nil) is the one inherited from TForm – Mario R. Jun 08 '15 at 09:22
  • I still don't really understand the problem. And this doesn't look very minimal to me. There's so much code that is surely not necessary that I for one cannot face looking into it. Please read that link that I provided carefully. – David Heffernan Jun 08 '15 at 09:23
  • @DavidHeffernan That's minimal. In the launcher part there's the function that i use to create the link between the launcher and the dll. the second function is the button that's calls the function from my dll. In the dll part there's the function called that simply calls Load_Frm and that return a certain valu (ok, cancel, ..) the last function is simply the load_Frm that create the form and use ShowModal to show it. That's all. There are of course other things that are made like checking if the data passed from the dll is ok, what type of data and so on that aren't involved in creating form – Mario R. Jun 08 '15 at 09:28
  • It's not an MCVE in my book. Never mind. I won't take this on. Maybe somebody else will. – David Heffernan Jun 08 '15 at 09:28
  • @DavidHeffernan It recreates the same thing i'm doing at minimal code. So it's basicly what you call a MCVE. As i told you, there only a .Create and that's all ;) – Mario R. Jun 08 '15 at 09:30
  • Can you please show us the contents of the constructor methods of your classes? – SilverWarior Jun 08 '15 at 11:37
  • If you'd shown an MCVE as I asked, we would not have had to guess. – David Heffernan Jun 12 '15 at 08:33

1 Answers1

4

It sounds like this is what you have done - let me guess at the steps to reproduce this problem:

  1. Created a base regular form - Let's call it TForm1
  2. Added a number of controls to TForm1
  3. Created a second regular form - Let's call it TForm2
  4. You then edited the .pas file containing TForm2 to have it inherit from TForm1 (ie : TForm2 = class(TForm1)
  5. You discovered that TForm2 did not contain any of the controls in TForm1, even though you "inherited" TForm1.
  6. You therefore copied and pasted the controls from the TForm1 designer to the TForm2 designer.
  7. This created a runtime error indicating that controls with the same name already existed. (Not a guess - you indicated this)
  8. You then renamed all of the duplicate controls in the descendent form (Not a guess - you indicated this)
  9. Now you have, at runtime, all the controls from the base form PLUS all the controls you copied and pasted (and renamed) into the descendent form. The form designer for the descendent form, however, does not show any of the ancestor controls at design time - only the new ones you have pasted in.

This is the incorrect way to create an inherited form using the visual designer.

To create an inherited form with design time editing you must select

File -> New -> Other...

From there, (this depends on the Delphi version, but for anything reasonably modern...) you select

Delphi Project -> Inheritable Items -> Form1

Where Form1 is the base form you wish to inherit. This should produce a new unit with a form that inherits both the class code as well as the DFM of the base form. If you look at the .dfm file (as text - push Alt+F12 in the designer) of the form created the wrong way you see at the top :

 object Form2: TForm2
   ...[etc]

whereas if you inherit correctly (as above) you will see the .dfm file begins as :

 inherited Form2: TForm2
   ...[etc]

Alternatively, you can create a regular form and modify the type declaration to inherit from the base form :

 TForm2 = class(TForm1)
  ...[etc]

but you must also make sure to modify the .dfm file from object to inherited. This ensures that the form designer correctly imports the controls belonging to the ancestor form.


The lesson here is that a design-time form contains two critical pieces of code.

  1. The class code in the .pas file
  2. The component design and layout information in the .dfm file

The error here is that you inherited only the class code (functionality) but did not inherit the design and layout information (content).

J...
  • 30,968
  • 6
  • 66
  • 143
  • Yeah this is what i did. I just checked and i don't have "Inhertiable items" in project. It's delphi 2006 btw, i don't find anything on the internet :( – Mario R. Jun 09 '15 at 07:11
  • @MarioR. `Inheritable Items` are only available if your project is open. – J... Jun 09 '15 at 08:41