Autor |
Beitrag |
Udo
Beiträge: 19
|
Verfasst: 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. 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.
Danke schon mal vorab
Udo Gerhards
|
|
Klabautermann
Beiträge: 6366
Erhaltene Danke: 60
Windows 7, Ubuntu
Delphi 7 Prof.
|
Verfasst: 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
Beiträge: 19
|
Verfasst: 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
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
|
Verfasst: Mo 28.10.02 23:53
Such mal das DLL-Tut unter www.assarbad.org. Da unter Quelltexte/Programme und etwas scrollen.
|
|
Udo
Beiträge: 19
|
Verfasst: Di 29.10.02 00:04
Danke,
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
Beiträge: 6366
Erhaltene Danke: 60
Windows 7, Ubuntu
Delphi 7 Prof.
|
Verfasst: 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
Beiträge: 19
|
Verfasst: 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
Beiträge: 6366
Erhaltene Danke: 60
Windows 7, Ubuntu
Delphi 7 Prof.
|
Verfasst: 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
Beiträge: 19
|
Verfasst: 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
Beiträge: 19
|
Verfasst: 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
Beiträge: 6366
Erhaltene Danke: 60
Windows 7, Ubuntu
Delphi 7 Prof.
|
Verfasst: 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.
Quelltext
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
Beiträge: 19
|
Verfasst: 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
Beiträge: 6366
Erhaltene Danke: 60
Windows 7, Ubuntu
Delphi 7 Prof.
|
Verfasst: 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:
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:
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
Beiträge: 19
|
Verfasst: 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
Beiträge: 6366
Erhaltene Danke: 60
Windows 7, Ubuntu
Delphi 7 Prof.
|
Verfasst: 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
Beiträge: 19
|
Verfasst: 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.
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
Beiträge: 6366
Erhaltene Danke: 60
Windows 7, Ubuntu
Delphi 7 Prof.
|
Verfasst: 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. |
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
Beiträge: 19
|
Verfasst: 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. 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:
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. 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
|
|
Udo
Beiträge: 19
|
Verfasst: 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.
Hier zuerst mal der Code:
Dll:
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:
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.
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
|
|
|