AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls Delphi Dynamisch erzeugte modulare Forms wie managen?
Thema durchsuchen
Ansicht
Themen-Optionen

Dynamisch erzeugte modulare Forms wie managen?

Offene Frage von "Dani"
Ein Thema von Dani · begonnen am 2. Okt 2004 · letzter Beitrag vom 5. Okt 2004
Antwort Antwort
Benutzerbild von Dani
Dani

Registriert seit: 19. Jan 2003
732 Beiträge
 
Turbo Delphi für Win32
 
#1

Dynamisch erzeugte modulare Forms wie managen?

  Alt 2. Okt 2004, 19:27
Hallo allerseits

Ich möchte (immer noch ) MDI-Child-Forms in
Packages speichern und aus einer seperaten Anwendung
heraus die compilierten BPL Dateien so laden, dass die
Anwendung dynamisch MDI-Children erstellen und
verwalten kann. Dabei sollen alle Vorzüge der VCL
erhalten bleiben.

Bisher löse ich das so:

Eine "Über-"Formklasse ableiten:

Delphi-Quellcode:
type
 TModularForm = class(TForm)
  private
    FProperty1: String;
    FProperty2: TStatusBar;
  public
    Edited: Boolean;
    procedure Foo1; virtual; abstract;
    procedure Foo2(aParam: String); virtual; abstract;
    function Foo3: String; virtual; abstract;
  published
    property Property1: String read FProperty1 write FProperty1;
    property Property2: String read FProperty2 write FProperty2;
  end;
Im Package: Exportierte Funktionen zur Initialisierung, Erzeugung von Forms usw.

Delphi-Quellcode:
unit uMyModularForm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ComCtrls {...};


type
  TMyModularForm = class(TModularForm)
   {....}
  private
    SomeInt: Integer;
  public
    procedure Foo1; override;
    procedure Foo2(aParam: String); override;
    function Foo3: String; virtual; override;
 {...}
  end;

var
 BPLApplication: TApplication;
 BPLScreen: TScreen;

procedure DrawModuleIcon(TargetBMP: TBitmap32);
function GetModuleName: PChar;
function CreateNewChild(aOwner: TComponent; LinkedStatusBar: TStatusBar): TModularForm;
function InitModule(GlobalApplication: TApplication; GlobalScreen: TScreen;
               var StatusStr: PChar): Boolean;

implementation

{...}

uses uAnotherForm;

function InitModule(GlobalApplication: TApplication; GlobalScreen: TScreen;
               var StatusStr: PChar): Boolean;
begin
 Result := true;
 try
  RegisterClass(TMyModularForm);
  RegisterClass(TAnotherForm);
 except
  Result := false;
  StatusStr := 'Ursache: Dieses Modul wurde bereits geladen. Das Programm wird nun terminiert.';
  exit;
 end;
 try
  BPLApplication := Application;
  Application := GlobalApplication;
  Application.Initialize;
 except
  Result := false;
  StatusStr := 'Ursache: Fehler bei der Übergabe des Application-Objekts. Das Programm wird nun terminiert.';
  exit;
 end;
 try
  BPLScreen := Screen;
  Screen := GlobalScreen;
 except
  Result := false;
  StatusStr := 'Ursache: Fehler bei der Übergabe des Screen-Objekts. Das Programm wird nun terminiert.';
  exit;
 end;
end;

procedure DrawModuleIcon(TargetBMP: TBitmap32);
begin
 {...}
end;

function GetModuleName: PChar;
begin
 Result := MODULENAME;
end;

function CreateNewChild(aOwner: TComponent; LinkedStatusBar: TStatusBar): TModularForm;
begin
 Result := TMyModularForm.Create(Application);
 Result.Property2 := LinkedStatusBar;
end;

exports
 DrawModuleIcon,
 GetModuleName,
 CreateNewChild,
 InitModule;

{...}

finalization
begin
 Application := BPLApplication;
 Screen := BPLScreen;
 UnRegisterClass(TMyModularForm);
 UnRegisterClass(TAnotherForm);
end;
Im Hauptprogramm ein neues Formular aus einem Modul erzeugen:
Delphi-Quellcode:
{...}
type
 TModuleEntry = class(TObject)
  public
    FileName: String;
    hModule : Cardinal;
    ModuleName: String;
    ModuleIcon: TBitmap32;
  end;

 TfrmMain = class(TForm)
  {...}
  private
   function GetActiveMDIChild: TModularForm;
   procedure AddChild(Kind: String);
  {...}
  end;

var
  ModuleList: TList; //Hier kommen Objekte vom Typ TModuleEntry rein

  procedure LoadModules;
  function GetModule(aFile: String): TModuleEntry;
    

implementation

function GetModule(aFile: String): TModuleEntry;
var StatusStr: PChar;
    GetModuleName: Function: PChar;
    DrawModuleIcon: procedure(TargetBMP: TBitmap32);
    InitModule: function (GlobalApplication: TApplication; GlobalScreen: TScreen;
                             var StatusStr: PChar): Boolean;
begin
 Result := nil;
 try
  Result := TModuleEntry.Create;
  Result.FileName := aFile;
  Result.hModule := LoadPackage(Result.FileName);
  @InitModule := GetProcAddress(Result.hModule, 'InitModule');
  If @InitModule = nil then raise Exception.Create('Funktion "InitModule" nicht gefunden.');
  If not InitModule(Application, Screen, StatusStr) then
   begin
    MessageBox(Handle,
               PChar('Das Modul "' + aFile + '" konnte nicht geladen werden.' + #13#10#13#10
                     + StatusStr),
               'Fehler beim laden des Moduls',
               MB_OK or MB_ICONERROR or MB_APPLMODAL);
    Application.Terminate;
    exit;
   end;
  @GetModuleName := GetProcAddress(Result.hModule, 'GetModuleName');
  If @GetModuleName = nil then raise Exception.Create('Funktion "GetModuleName" nicht gefunden.');
  @DrawModuleIcon := GetProcAddress(Result.hModule, 'DrawModuleIcon');
  If @DrawModuleIcon = nil then raise Exception.Create('Funktion "DrawModuleIcon" nicht gefunden.');
  Result.ModuleName := GetModuleName;
  Result.ModuleIcon := TBitmap32.Create;
  Result.ModuleIcon.Width := 32;
  Result.ModuleIcon.Height := 32;
  DrawModuleIcon(Result.ModuleIcon);
 except
  If Assigned(Result) then FreeAndNil(Result);
  raise;
 end;
end;
    
procedure LoadModules;
var R: TSearchRec;
    FoundCount: Integer;
    ModuleEntry: TModuleEntry;
begin
 FoundCount := 0;
  If FindFirst(RootDir + 'Modules\*.bpl', faAnyFile-faDirectory, R) = 0 then
   Repeat
    try
     ModuleEntry := GetModule(RootDir + 'Modules\' + R.Name);
     ModuleList.Add(ModuleEntry);
     inc(FoundCount);
    except
     on E: Exception do
      MessageBox(0,
                 PChar('Das Modul "' + R.Name +'" konnte nicht geladen werden.' + #13#10 +
                       'Ursache: ' + E.Message),
                 'Fehler',
                 MB_OK or MB_ICONERROR);
    end;
   Until FindNext(R) <> 0;
   FindClose(R);
   Case FoundCount of
    0: frmMain.StatusBar1.Panels[1].Text := 'Keine Module geladen...';
    1: frmMain.StatusBar1.Panels[1].Text := '1 Modul geladen...';
    else frmMain.StatusBar1.Panels[1].Text := IntToStr(FoundCount) + ' Module geladen...';
   end;
end;

function TfrmMain.GetActiveMDIChild: TModularForm;
var i: Integer;
begin
 Result := nil;
 for i:=0 to MDIChildCount-1 do
  If MDIChildren[i].Active then
   begin
    Result := TModularForm(MDIChildren[i]);
    exit;
   end;
end;

procedure TfrmMain.AddChild(Kind: String);
var NewForm: TModularForm;
    CreateNewChild: Function(aOwner: TComponent; LinkedStatusBar: TStatusBar): TModularForm;
    ModuleEntry: TModuleEntry;
    i: Integer;
    ModuleFound: Boolean;
begin
  ModuleFound := false;
  for i:=0 to ModuleList.Count-1 do
   begin
    ModuleEntry := TModuleEntry(ModuleList[i]);
    If ModuleEntry.ModuleName = Kind then
     begin
      @CreateNewChild := GetProcAddress(ModuleEntry.hModule, 'CreateNewChild');
      If @CreateNewChild = nil then raise Exception.Create('Die Funktion CreateNewChild wurde im Modul "' + ModuleEntry.ModuleName + '" nicht gefunden');
       NewForm := CreateNewChild(Application, StatusBar1);
       NewForm.Property1 := 'TestTest';
       NewForm.OnClose := MDIChildClose;
       NewForm.WindowState := wsMaximized;
       ModuleFound := true;
     end;
   end;
end;
Zur Erklärung: Die Application, und Screen -Variablen der Module müssen beim initialisieren überschrieben werden, damit die Erstellung von MDI-Children und die zugehörige Variable MDIChildCount funktionieren.
Nun meine eigentliche Frage: Ist dies wirklich der "einzig wahre" Weg, um MDI-Child-Forms in Packages auszulagern, oder mache ich hier etwas falsch? Tausend Dank schonmal fürs lesen
Dani H.
At Least I Can Say I Tried
  Mit Zitat antworten Zitat
Benutzerbild von Dani
Dani

Registriert seit: 19. Jan 2003
732 Beiträge
 
Turbo Delphi für Win32
 
#2

Re: Dynamisch erzeugte modulare Forms wie managen?

  Alt 4. Okt 2004, 19:49
Hmm, ich werd mal ein Testprojekt schreiben, vielleicht ist das ja irgendwie nützlich...
Dani H.
  Mit Zitat antworten Zitat
Benutzerbild von Dani
Dani

Registriert seit: 19. Jan 2003
732 Beiträge
 
Turbo Delphi für Win32
 
#3

Re: Dynamisch erzeugte modulare Forms wie managen?

  Alt 4. Okt 2004, 23:38
Okay, hier das Beispielprojekt...selbst bei dieser einfachen Anwendung kommt es zu sehr.... interessanten Fehlern

Edit: Der Quelltext aus dem ersten Post ist übrigens nicht mehr aktuell, bitte ignorieren.
Angehängte Dateien
Dateityp: rar modulare_forms_test.rar (70,4 KB, 34x aufgerufen)
Dani H.
  Mit Zitat antworten Zitat
Benutzerbild von Dani
Dani

Registriert seit: 19. Jan 2003
732 Beiträge
 
Turbo Delphi für Win32
 
#4

Re: Dynamisch erzeugte modulare Forms wie managen?

  Alt 5. Okt 2004, 23:29
Ich bleib mal optimistisch
Dani H.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:36 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz