Autor Beitrag
Udo
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Mo 28.10.02 21:03 
Hallo zusammen,

daß was ich vorhabe, ist nicht gerade einfach und deshalb brauch ich Eure Hilfe. Ich möchte eine Anwendung erstellen, bei der sich die Oberflächen verändern können. Sprich es soll eine Anwendung werden, bei der die Oberflächen über eine DLL nachgeladen werden können. Weiterhin sollen aber auch in dieser Anwendung nicht visuelle Funktionen über eine DLL bereitgestellt werden und diese durch die einzelnen Oberflächen ansprechbar und nutzbar sein. Dabei sollen die DLL's zur Laufzeit nachgeladen werden. :shock: Die Grundfunktionen (z.B. Einbinden von DLL's) sind mir klar, aber das Ganze ist doch ziemlich komplex, deshalb, weiß hier jemand ein gutes Tutorial (z.B. Forms in DLL's, etc.) welches sich schon mal mit sowas befasst hat oder hat vielleicht jemand von Euch schon Erfahrungen mit einer solchen Anwendung gemacht.

Wäre super, wenn Ihr mit weiterhelfen könntet. :D

Danke schon mal vorab

Udo Gerhards
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: Mo 28.10.02 21:51 
Hallo,

wenn du mit Oberflächen ganze Forms meinst, die dann wie Dialoge Quasi "Stand allone" aus der DLL angezeigt werden ist das überhaubt kein Problem. Du erstellst das Formular einfach in einer 2ten Unit deiner DLL und exportierst ein Show Methode.

Wenn du hingegen MDI-Childs oder Panels oder soetwas in deine Anwendung importieren willst, dann vergiss es. Dazu sind DLLs nicht geeignet. Die sind nicht mehr die jüngsten und bieten somit weinerlei Möglichkeiten mit Objekten zu arbeiten oder Komplexe Datenstrukturen sinvoll zu übergeben. Desweiteren läuft die DLL in einem anderen Speicherbereich als die EXE. Auch das macht Probleme.

Gruß
Klabautermann
Udo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Mo 28.10.02 23:19 
Titel: Hmmm, klingt nicht gut ....
Hallo Klabautermann,

klingt nicht gut, was Du mir da sagst. Im Prinzip soll es eine Anwendung werden, die sowohl Forms, als auch andere Komponenten (wie z.B. Panels oder auch MDI-Childs) dynamisch einbinden soll.
Ich dachte an eine Grundform, in der je nach Bedarf ganze Forms eingebunden oder eben nur Teile dieser Forms ersetzt werden sollten. Quasi eine multifunktionale Anwendungsoberfläche.
Gibts sowas überhaupt und wenn ja, gibts zu diesem Thema vielleicht ein Tutorial ?
Gesehen habe ich sowas mal beim Beispiel für den VirtualTree von Mike Lischke. Allerdings hat Mike hierbei nur ganze Forms eingebunden, keinen einzelnen Komponenten. Außerdem waren alle Forms in einer Applikation zusammengefasst und nicht dynamisch erweiterbar bzw. eben nicht über verschiedene DLL's eingebunden.

mfg

Udo :cry:

P.S.: Vielleicht sollte ich noch dazu sagen, daß Mike die einzelnen Forms einfach mit einer form*.parent-Anweisung im Hauptfenster an ein Panel angebunden hat.
Popov
Gast
Erhaltene Danke: 1



BeitragVerfasst: Mo 28.10.02 23:53 
Such mal das DLL-Tut unter www.assarbad.org. Da unter Quelltexte/Programme und etwas scrollen.
Udo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Di 29.10.02 00:04 
Danke, :wink:

das hat schon mal meine Frage zu den Forms beantwortet. Klabautermann sprach aber davon, daß es nicht ratsam wäre, Panels, MDI-Childs oder ähnliches in DLL's auszulagern. Funktioniert die im Tutorial beschriebene Möglichkeit jetzt auch bei anderen Objekten oder gibts hier ne gesonderte Verfahrensweise?

mfg

Udo
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: Di 29.10.02 02:01 
Hallo,
Popov hat folgendes geschrieben:
Such mal das DLL-Tut unter www.assarbad.org. Da unter Quelltexte/Programme und etwas scrollen.

stimmt, da hab es ja noch Borland Memory-Manager (siehe das Tutorial). Der könnte dich ein Stuck weiter bringen.
Alerdings ist dieser keine Option wenn das ganze eine Art PlugIn System sein soll, das auch für andere Offen ist. Denn du kannst nicht davon ausgehen, das jeder Programmierer zugriff auf diesen Hat. Ich weiß nicht wie sich eine Visual Basic DLL damit versteht. Wenn mir hier jetzt jemand erklährt, das das alles kein Problem sei und wie es geht würde ich mich freuen, aber irgendwie glaube ich nicht dran.
Wenn es hingegen ein System nur für dich ist, dann solltest du dich mal mit BPLs (Packages) auseinander setzen, das sind im grunde modernere Objekt Orientierte DLLs, allerding sind diese 1. von Borland und 2. Versionsabhängig. Im grunde müssen deine EXE und die Packages immer mit der selben Compilerversion übersetzt sein, da sie sonst inkompatibel werden.
Eine dritte Möglichkeit währe noch COM, frage mich aber bitte nicht wo da die grenzen liegen.
Fakt ist, ich kenne auch keine praktikable Lösung (bei COM reicht mein wissen aber nicht sehr weit), ich kenne aber einige Leute (inklusieve mir) die es mit Standart DLLs nicht hinbekommen haben.
Wenn du dir mal Plugin Schnitstellen ansiehst, die im einsatz sind, wirst du feststellen, das Visuelle Möglichkeiten meist über eine API realisiert werden.

Gruß
Klabautermann
Udo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Di 29.10.02 02:14 
Na ja,

von meiner Seite aus ist angedacht, daß gesamte Projekt mal als OpenSource ins Netz zu stellen.
Der Code der Hauptanwendung soll allerdings dabei unangetastet bleiben. Es soll eben nur die Möglichkeit geben, angefangen von der gesamten Oberfläche bis hin zum kleinsten Panel, die Komponenten auszutauschen. Also dachte ich mir, DLL's seien die günstigste Lösung. Mit einer Art Initialisierungsroutine versehen, könnte ich die dann vom Hauptprogramm auslesen lassen und eben nur die entsprechenden Komponenten verändern. Das Ganze soll vorerst mal für Delphi-Programmierer offenstehen. Allerdings wäre es schon super, wenn Leute mit anderen Systemen ebenfalls dran arbeiten könnten.

BPL's kommen da, allein schon wegen der möglichen Verbreitung, wohl schlecht in Frage.

Apropos Memory-Manager. Soweit ich weiß wird der doch dann benötigt, wenn Strings etc. übergeben werden sollen. Wenn ich jetzt aber nur Pointer auf die jeweiligen Strings der DLL zurückgebe, wie siehts dann aus ? Brauch ich ihn dann unbedingt ....

Ich weiß, es klingt alles sehr phantastisch und sehr komplex, aber mir ist es erst mal wichtig, die theoretischen Grundlagen und die Möglichkeiten für solch eine Anwendung zu kennen, um mich dann zu entscheiden ob ich mich dran mache oder ob ich es lieber sein lasse.

Danke nochmal

Udo
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: Di 29.10.02 11:59 
Hallo,
Udo hat folgendes geschrieben:
Apropos Memory-Manager. Soweit ich weiß wird der doch dann benötigt, wenn Strings etc. übergeben werden sollen. Wenn ich jetzt aber nur Pointer auf die jeweiligen Strings der DLL zurückgebe, wie siehts dann aus ? Brauch ich ihn dann unbedingt ....

Also bei Stings kannst du problemlos über PChar gehen. Wie es mit ^String ist, kann ich nicht sagen. Ich habe es mit Pointer auf Panels und ähnlichen vor einer weile Probiert und nicht befriedigend hinbekommen. Mit wurde das Damals mit den Unterschiedlichen Adressräumen erklährt. Das umsetzen von Parrent hat damals nicht geklappt.
Wenn du es hinbekommen solltes währe es nett wenn du das ganze hier (vieleicht als Tutorial) veröffentlichst.

Gruß
Klabautermann
Udo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Di 29.10.02 12:41 
Hallo Klabautermann, :)

ich bin grad an einem Testlauf mit einer kleinen DLL dran. Dort gibt mir eine Funktion einen Pointer auf ein TStringList-Objekt zurück. Allerdings habe ich anscheinend die gleichen Probs wie Du sie hattest. Das Proggi bricht im Moment noch mit einer "Anwendungsinternen Exception at memory ..."-Fehlermeldung ab, wenn ich versuche die Funktion aufzururfen. Aber ich werd es weiterversuchen.

Sollte es dann klappen werde ich auf alle Fälle den Source-Code hier veröffentlichen.

mfg + Danke

Udo
Udo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Di 29.10.02 21:16 
Nochmal ich !

Klabautermann, kannst Du mir mal mitteilen, welche Fehler Du angezeigt bekommen hast. Im Moment scheitere ich schon an dem Versuch, ein einfach TStringListen-Objekt in der DLL erzeugen zu lassen.
Kann das unter Umständen an einer fehlerhaften Speicherverteilung liegen. Der MemoryManager ist derzeit noch nicht mitinstalliert.

mfg

Udo
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: Mi 30.10.02 11:26 
Hallo,

da muss ich wenn ich ZEit habe mal alte Backup CDs durchwühlen, ist nämlich schon 'ne Weile her. Ich glaube aber es war eine Zugriffsverletzung at Adresse xy.
Inerhalb der DLL solltest du Stinglisten Problemlos erstellen können.
ausblenden Quelltext
1:
tStringList.Create;					

Eine übergabe an das Programm sollte hingegen Problematisch werden.

Also wie gesagt, für die konkrete Fehlermeldung muss ich CDs durchgucken was mir momenan nicht möglich ist.

Gruß
Klabautermann
Udo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Mi 30.10.02 17:05 
Kein Thema,

dachte nur, Du hättest Sie parat. Diese Fehlermeldung bekomme ich bereits, wenn ich die Stringliste erstelle. Ich habe hier nochmal einen extra Thread gepostet, auch deshalb, weil ich überlegt habe den MemoryManager einzusetzen. Aber soweit ich mich jetzt mit dem Thema befasst habe, denke ich, ist der Einsatz einer solchen DLL für meine Zwecke nicht ratsam.
Ich werde wohl wirklich auf COM-Objekte ausweichen müssen und da tauchen neue Probleme auf. Wenn Du hierzu ein gutes Tutorial weißt, bin ich Dir auf ewig dankbar. Insbesondere die Programmierung von COM-Objekten, sowie die Veröffentlichung von Methoden/Ereignissen über den TypeLibrary-Editor sind hierbei Themen, die ich noch nicht so verstehe und mit denen ich mich wohl oder übel beschäftigen muß.

Ach ja, zur DLL nochmal. Es sollte eigentlich nur ein Pointer auf die Stringliste ans Programm übergeben werden. Aber wie gesagt, lässt sie sich mit TStringList.Create nicht erstellen. Wahrscheinlich habe ich irgendwo eine Bug im Code. Werde es trotzdem mal weiter versuchen.

Also, danke auf alle Fälle schon mal für alles ...

Udo
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: Mi 30.10.02 17:41 
Hallo,

Udo hat folgendes geschrieben:
Diese Fehlermeldung bekomme ich bereits, wenn ich die Stringliste erstelle. Ich habe hier nochmal einen extra Thread gepostet, auch deshalb, weil ich überlegt habe den MemoryManager einzusetzen.

ich dem anderen Thread hast auch gesagt bekommen was Falsch war, du hast etwas in dieser richtung Probiert:
ausblenden Quelltext
1:
2:
3:
4:
VAR
  SL : tStringList;
begin
  SL.Create;

Das kann nicht klappen denn SL existiert ja noch nciht (nur ein Zeiger drauf) und deshalb kannst du SL.Create nicht aufrufen. Du musst also tatsächtich das Objekt mit tStringLis.reate erzeufen und es Quasi mit SL auffangen:
ausblenden Quelltext
1:
2:
3:
4:
VAR
  SL : tStringList;
begin
  SL := tStringList.Create;



Udo hat folgendes geschrieben:
Ich werde wohl wirklich auf COM-Objekte ausweichen müssen und da tauchen neue Probleme auf. Wenn Du hierzu ein gutes Tutorial weißt, bin ich Dir auf ewig dankbar.


Da kann ich nicht mit dienen. Was hast du denn für Bücher im Regal?

Gruß
Klabautermann
Udo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Mi 30.10.02 17:51 
Hallo,

was die Bücher anbelangt nicht sehr viel. "Borland Delphi 5.0 - Grundlagen und Profiwissen", die Delphi 6.0-Onlinehilfe auf Englisch und ein paar Tutorials bzw. Ebooks (etwa 2, die sich aber alle mit Grundlagen beschäftigen).
Das meiste, was ich weiß, habe ich aus der Online-Hilfe und aus dem o.g. Buch. Allerdings werden aber eben dort solche tiefergehenden Sachen, wie COM-Programmierung etc. nur oberflächlich besprochen. Mir ist z.B. immer noch nicht ganz klar, ob ich für eigene COM-Objekte eine OLE-Containter zwingend in mein Programm einbinden muß, um COM-Objekte nutzen zu können oder ob ich diese Objekte einfach nur einbinden und dann in meinem Programm "createn" kann.

Das sind alles Fragen, die leider nicht in meinen Büchern stehen.

mfg

Udo
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: Do 31.10.02 14:36 
Hallo,

ich blättere grade durch die aktuelle Toolbox welche heute in meinem Briefkasten lag und bin darbei auf einen Artikel zu COM gestoßen.
Dieser ist in der Ausgabe 6'02 auf den Seiten 52-55 und heißt "Behind the (Inter)face" von Jens Geyer, fallst du diese Zeitschift besitzt oder zugriff drauf hast kann es nicht schaden diesen mal zu lesen (ich habe es noch nicht ;)). Aber am ende des Artikels werden 2. URLs empfohlen die für dich vieleicht interessant sind:
www.codeguru.com
www.codeproject.com
auch diese habe ich noch nicht unter die Lupe genommen aber vieleicht helfen sie dir ja.

Viel Erfolg
Klabautermann
Udo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Do 31.10.02 15:26 
Danke,

ich werd sie mir gleich mal anschauen. So wie es aussieht werde ich jetzt auf COM ausweichen. Ein bischen habe ich mich schon eingearbeitet. Allerdings habe ich Probs beim Einbinden von Forumlaren in den ActiveX-Server. Dort funktionieren anscheinend nur ActiveX-Formulare und nicht die Standartforms, wie eine ordinäre MDI-Form. Aber ich werds rausbekommen, wie es funktioniert, hoffe ich zumindest. :wink:

Ach ja, hattest Du nicht davon was gesagt, daß die Geschichte mit dem form.parent bei Dir nicht hingehauen hat ? Ich habe mir gestern nochmal den Code von Mike Lischke's Beispielen angesehen. Er hat's dort tatsächlich geschafft. Wenn es Dich interessiert, kann ich Dir hier mal den Code posten.

mfg

Udo
Klabautermann
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Veteran
Beiträge: 6366
Erhaltene Danke: 60

Windows 7, Ubuntu
Delphi 7 Prof.
BeitragVerfasst: Do 31.10.02 15:55 
Hallo,
Udo hat folgendes geschrieben:
So wie es aussieht werde ich jetzt auf COM ausweichen. Ein bischen habe ich mich schon eingearbeitet. Allerdings habe ich Probs beim Einbinden von Forumlaren in den ActiveX-Server. Dort funktionieren anscheinend nur ActiveX-Formulare und nicht die Standartforms, wie eine ordinäre MDI-Form. Aber ich werds rausbekommen, wie es funktioniert, hoffe ich zumindest. :wink:

Wie währe es, wenn du (vieleicht per Callback Funktion) leere MDI-Childs von deinen HAuptprogramm erstellen lässt und diese dann als Container für deine COM-Objekte verwendest. Ist nur 'ne wilde nicht weiter durchdachte Idee aber vieleicht hilft es dir ja. ;)

Udo hat folgendes geschrieben:
Ich habe mir gestern nochmal den Code von Mike Lischke's Beispielen angesehen. Er hat's dort tatsächlich geschafft. Wenn es Dich interessiert, kann ich Dir hier mal den Code posten.


Gerne, irgendwann in den nächsten Monaten werde ich mich wieder an das Problem machen müssen. Vieleicht bringt das ja ein gute Idee.

Gruß
Klabautermann
Udo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Do 31.10.02 18:10 
Hallo Klabautermann,

das mit den MDI-Childs ist schon eine gute Idee, aber ich will doch durch die COM-Objekte die ganze Oberfläche verändern lassen. Da brauch ich dann auch MDI-Rahmenfenster. Vielleicht probier ich es einfach mal so, wie Mike das gemacht hat. Ich erstell ne ActiveXForm, plaziere darauf dann einen Panel und lade dann über form.parent die MDI-Form auf den Panel. Vielleicht funktionierts ja. :shock: Wenn nicht, dann muß ich mir zwangsläufig was anderes einfallen lassen. Jedenfalls habe ich auf den Thread, den ich hier gepostet habe auch noch keine Antwort erhalten.
Also werde ich es doch ausprobieren müssen.

Hier ist auf alle Fälle mal der Code, den Mike zum einbinden der Formulare benutzt hat:
ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
procedure TMainForm.DemoButtonClick(Sender: TObject);

// This method is a kind of scheduler. Here we switch between the demo forms.

var
  NewDemoClass: TFormClass;
  NewDemo: TForm;

begin
  case (Sender as TSpeedButton).Tag of
    0:
      NewDemoClass := TSpeedForm;
    1:
      NewDemoClass := TGeneralForm;
    2:
      NewDemoClass := TPropertiesForm;
    3:
      NewDemoClass := TVisibilityForm;
    5:
      NewDemoClass := TGridForm;
    6:
      NewDemoClass := TDrawTreeForm;
    7:
      NewDemoClass := TAlignForm;
    8:
      NewDemoClass := TWindowsXPForm;
  else
    NewDemoClass := nil;
  end;

  if (ContainerPanel.ControlCount = 0) or not (ContainerPanel.Controls[0] is NewDemoClass) then
  begin
    if ContainerPanel.ControlCount > 0 then
      ContainerPanel.Controls[0].Free;

    if Assigned(NewDemoClass) then
    begin
      NewDemo := NewDemoClass.Create(Self);
      NewDemo.Hide;
      NewDemo.BorderStyle := bsNone;
      NewDemo.Parent := ContainerPanel;
      NewDemo.Align := alClient;
      NewDemo.Show;
    end;
  end;
end;

Wie gesagt hat er einfach auf eine normale Form einen Panel aufgesetzt und dann die Forms, die nachgeladen wurden mit form.parent an diesen Panel gebunden. In seinem Beispiel funktioniert es ganz gut. Wundert mich, daß Du den Treeview von ihm nicht kennst. Ist ein verdammt geniales Teil. 8) Hier mal der Link zu seiner Seite:

www.delphi-gems.com oder
www.lischke-online.de

Ist fast eine "must have"-Komponente. Dort findest Du auch das o.g. Beispiel.

Also, ich werde Dich jedenfalls mal von Zeit zu Zeit auf dem Laufenden halten, wie das mit der COM-Programmierung läuft.

mfg

Udo :wink:
Udo Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Do 14.11.02 00:58 
O.K.,

nachdem ich lange genug ausprobiert, rumgetüfftelt und meine Nervern überstrapaziert habe, habe ich nun endlich die ersten Ergebenisse. :D
Hier zuerst mal der Code:

Dll:


ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
library testdll;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

uses
  SysUtils,
  Windows,
  Classes,
  Forms,
  Dialogs,
  baseunit in 'baseunit.pas' {base},
  basechildunit in 'basechildunit.pas' {basechild};

{$E dll}

{$R *.res}

var
DLLProcNext: procedure(Reason: Integer); stdcall = nil;

procedure DLLMain(Reason: Integer); stdcall;
begin
 case Reason of
        DLL_PROCESS_ATTACH:
                begin
                DisableThreadLibraryCalls(hInstance);
                application.CreateForm(Tbase, base);
                end
                ;
        DLL_THREAD_ATTACH:
                ;
        DLL_THREAD_DETACH:
                ;
        DLL_PROCESS_DETACH:
                ;
 end;
 if Assigned(DLLProcNext) then DLLProcNext(Reason);
end;

function initialize:Pointer; stdcall;
begin
result := base;
end;

//exports-Abschnitt

exports
        initialize;

begin
DLLProcNext := Pointer(InterlockedExchange(integer(addr(DLLProc)),integer(@DLLMain)));
DLLMain(DLL_PROCESS_ATTACH);
end.


Das ist die Hauptunit der DLL. Wenn Sie geladen wird (bei mir im Hauptprogramm dynamisch) mach sie nix anderes, als einfach ein MDI-Formular zu erzeugen. Danach wird über den Aufruf der "initialize"-Routine der Pointer auf das erzeugte Formular zurückgegeben. In der DLL sind noch zwei weitere Units untergebracht, eine für das Hauptfenster ("baseunit") und eine für das MDI-Child ("basechildunit").

Wie gesagt wird diese DLL durch das Hauptprogramm dynamisch geladen und dann die "initialize"-Routine aufgerufen, um den Pointer auf das erzeugte MDI-Formular zu erhalten. Danach wird einfach im Hauptprogramm mit dem Pointer weitergearbeitet. Der Code des Hauptprogramms sieht folgendermaßen aus:

Hauptprogramm:

ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
unit mainform;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, sharemem, ExtCtrls, StdCtrls, AXCtrls;

type Tinit_dll = function:Pointer;

type
  Thost = class(TForm)
    procedure FormShow(Sender: TObject);
    procedure FormResize(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  host: Thost;
  desktop : TActiveForm;

implementation

{$R *.dfm}

procedure Thost.FormShow(Sender: TObject);
var
init_dll : Tinit_dll;  
init_func : TFarProc; 
dllhandle : THandle;  
address : Integer;
newbase : Pointer;
begin
dllhandle := LoadLibrary('testdll.dll');
init_func := GetProcAddress(dllhandle,'initialize');
if init_func <> nil then
        begin
        @init_dll := init_func;
        newbase:=init_dll;
        desktop := TActiveForm(newbase);
        desktop.ParentWindow := host.Handle;
        desktop.setbounds(0,0,host.ClientWidth+1, host.clientheight+1);
        desktop.UpdateControlState;
        desktop.WindowState := wsmaximized;
        desktop.Show;
        end
        else showmessage('Dll wurde nicht geladen');
end;

procedure Thost.FormResize(Sender: TObject);
begin
desktop.SetBounds(0,0,host.clientwidth,host.clientHeight);
end;

end.


Soweit funktioniert auch alles und die MDI-Form wird innerhalb der Hauptoberfläche angezeigt. Allerdings konnte ich bisher zwei Einschränkungen feststellen. Zum einen kann bei dem MDI-Formular kein normales MainMenue benutzt werden, da es nach dem "Binden" ans Hauptformular nicht angezeigt wird. Deshalb bin ich auf die TBX-Items (bzw. Toolbar2000-Items) von Jordan Russel und Alex Denisov ausgewichen (Beide Packages kann man bei www.torry.net als Freeware / Shareware runterladen).
Der Vorteil bei diesen Items ist, man hat ganz normale Toolbars, die man auch als MainMenue für das Fenster nutzen kann. Außerdem realisieren sie den XP-Style auch unter Windows 2000. 8)

Das zweite Problem ist leider nicht so einfach zu lösen. Wenn ich ein MDI-Child-Formular erzeuge und dieses maximiere erhalte ich folgende Fehlermeldung:

Access violation at address 77E1E7AC in module 'user32.dll'. Read of address 000403DA !!

Das komische bei der Sache ist, daß dieser Fehler nicht immer auftritt. Ich habe mittlerweile verschiedene Testläufe des Programms durch und ab und zu werden die Childs normal maximiert und ich kann ganz normal damit arbeiten, ohne das irgendein Fehler erzeugt wird.

Hat hier jemand eine Ahnung, warum der Fehler mal auftaucht und mal nicht ?

Wäre super, wenn mir jemand helfen könnte.

mfg

Udo