AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi Zugriff auf Komponenten auf einer Form in einer DLL
Thema durchsuchen
Ansicht
Themen-Optionen

Zugriff auf Komponenten auf einer Form in einer DLL

Ein Thema von TPok · begonnen am 28. Sep 2005 · letzter Beitrag vom 28. Sep 2005
Antwort Antwort
TPok

Registriert seit: 19. Jul 2004
Ort: Eisenach
25 Beiträge
 
Delphi 2005 Professional
 
#1

Zugriff auf Komponenten auf einer Form in einer DLL

  Alt 28. Sep 2005, 16:12
Hallo,

hab in Anlehnung an Assarbads Tutorial eine DLL erstellt, die ein Form mit einigen Komponenten enthält. Die einzige enthaltene und exportiere Funktion lautet:

Delphi-Quellcode:
function ShowForm: Pointer; stdcall;
begin
  frmListe := TfrmListe.Create(nil);

  frmListe.Show;
  Result := frmListe;
end;
Im Haupprogramm binde ich die DLL dynamisch ein und erzeuge das Formular.
Delphi-Quellcode:
var
  frmListe: TForm;
...
frmListe := ShowForm;
Ein Zugriff auf Die Komponenten des Formular gelingt problemlos durch
Delphi-Quellcode:
For i := 0 to frmListe.ComponentCount - 1 do
  If frmListe.Components[i].Name = 'btnOkthen
    TButton(frmListe.Components[i]).OnClick := btnOkClick;
Es scheitern aber Dinge wie
Delphi-Quellcode:
If frmListe.Components[i].ClassType = TButton then // ClassType hat keinen sinnvollen Wert

If frmListe.Components[i] is TButton then // Geht ebensowenig

(frmListe.Components[i] as TButton).OnClick := btnOkClick; // ungültiger Typecast
Kann mir dieses Verhalten bitte jemand erklären und ggf. Lösungswege aufzeigen?

Ich weiß, dass das alles keine sauber OOP ist und ich böse viele Sachen tue. Im meinem Anwendungsfall macht es aber Sinn.

Kurz zur Erläuterung:
Ich möchte die DLLs als einfache dumme Container für ein Formular verwenden. Ich habe ein Hauptprogramm, dass als Parameter den Namen der DLL erhält. Nach dem Start zeigt es das Formular aus der DLL an. Nach dem Klick auf dem Ok-Button auf diesem Formular liest das Hauptprogramm die Eingaben aus den einzelnen Controls aus und übergibt sie an einen in Crystal Reports erstellte Datenbankauswertung. Dabei wird die Zuornung zwischen Parameter der Datenbankauswertung und dem Control über Namen und Typ des Controls hergestellt.
Die gesamte "Intelligenz" soll im Hauptprogramm stecken, so daß zu jeder Datenbankauswertung nur eine DLL mit einem Formular erstellt werden muß und fertig.

Ich hoffe, das war jetzt einigermaßen verständlich.

Liebe Grüße,
Stephan
Stephan Fietzek
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#2

Re: Zugriff auf Komponenten auf einer Form in einer DLL

  Alt 28. Sep 2005, 17:18
Lösungen:

1.) mit Packages arbeiten, oft hier im Forum erklärt
2.) darauf verzichten und per .ClassName abfragen, was wiederum nur getrickse wäre

Ursache:

Beides, dein Code der EXE und der Code der DLL linken die VCL komplett als separate Kopie in ihren Code ein. Alle Abfragen wie is, as gehen auf die Methoden .ClassType und .ClassParent zurück die einfach einen Pointer in das Codesegement liefern in der die Klassenstruktur durch den Compiler gespeichert wurde. Da aber nun beide Module, EXE wie auch DLL, eine egene Kopie dieser Klassenstrukturen speichern wird ein Vergleich dieser Pointer untereinander unterschiedliche Klassenstrukturen vergleichen. Dieser Vergleich kann also niemals TRUE ergeben. Da aus Sicht der Klassenhierarchie es sich um zwei vollkommen getrennte Kopien handelt.

Dieser Fakt zeigt sehr deutlich das in einer komplexeren Anwendung die auf einem solchen DLL Konzept aufbaut auf kurz oder lang immense Probleme zukommen werden. Weil

1.) die VCL auf die is,as,ClassType Operatoren angeweisen ist
2.) weil es durchaus möglich ist das zb. das EXE Modul dynamisch eine Klasse erzeugt die aber in einer Objektinstance die durch die DLL erzeugt wurde eingefügt wird. Sprich: die EXE erzeugt Komponente X und fügt diese in Form Y, das in der DLL erzeugt wurde, ein. Nun vermischen sich also zwei im Grunde verschiedene Klassenhierarchien in einer Objektinstance. Wird diese aber nun freigegeben wird NICHT per IS,AS Operator vorher geprüft zu welcher Klassenhierarchie die jeweilige Komponente gehört sondern einfach freigegeben. Es vermischt sich also auch die Verantwortlichkeit wer was wann an Daten freizugeben hat. Das funktioniert so lange gut wie beide Module mit dem gleichen Speichermanager arbeiten. Aber auf lange Sicht wird es krachen und zu sehr unschönen Fehlern führen.

Basis der Ursache:

ist darin begründet das es in fakt nicht möglich ist auf diese Weise die VCL in eigenen Modulen zu vergewaltigen. Dies ist niemals so vorgesehen gewesen. Die grundsätzliche Ursache liegt also im Unvermögen derjenigen Programmierer die solche Tricks als saubere Lösung vorschlagen und nicht die Zusammenhänge der VCL begriffen haben. Ist leider so, und ich rate dir von solchen Lösungen Abstand zu nehmen.


Gruß Hagen
  Mit Zitat antworten Zitat
TPok

Registriert seit: 19. Jul 2004
Ort: Eisenach
25 Beiträge
 
Delphi 2005 Professional
 
#3

Re: Zugriff auf Komponenten auf einer Form in einer DLL

  Alt 28. Sep 2005, 17:39
Hallo Hagen,

ich hab den Fingerzeig verstanden.

Setzen wir bei dem Problem mal eine Stufe tiefer an. Welche anderen Möglichkeiten habe ich denn, die kurz umrissene Funktionalität zu realisieren?

Ich habe 1. den Report aus Crystal Reports und kann 2. einen Viewer mit Eingabefeldern für Parametern in Delphi dafür programmieren. Ich denke, die ganze Geschichte soweit zu "zentralisieren", dass die gesamten Anzeige- und Exportroutinen nur einmal vorhanden sind, ist schonmal nicht falsch.
Bleibt das Problem mit der Oberfläche, die jedes Mal ähnlich funktioniert, aber anders aussieht (andere Anzahl Felder, Labels zur Beschriftung, etc.) und möglichst schnell und einfach entworfen werden soll.

Mir fallen da spontan 2 Lösungen ein:
1. Design des Formulars in Delphi und Auslagerung in eine Separate Datei, die von der Hauptanwendung geladen werden Kann. Die Probleme damit sind ja oben hinreichend beschrieben.

2. Eine Ini-Datei (o.ä.) mit Feldtyp, Koordinaten, etc., welche vom Viewerprogramm eingelesen wird und die Komponenten zur Laufzeit auf einem seiner Forms erstellt. Prinzipiell möglich und realisierbar. Aber dann kann man das Formular nicht mehr grafisch zusammenklicken und falls man doch mal etwas mehr Funktionalität braucht (z.B. Feld A + Feld B = Feld C), hat man Pech.


Ich bin für jeglichen Vorschlag offen.

Liebe Grüße,
Stephan
Stephan Fietzek
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#4

Re: Zugriff auf Komponenten auf einer Form in einer DLL

  Alt 28. Sep 2005, 18:07
Suche mal nach "Forms in Packages" oder so.

Nur kurz: benutzt du Packages erledigt sich das ganze Problem. Packages + EXE mit Packages + Formular DLLs mit Packages stellen sich im Speicher so dar als wären sie aus einem Guß, als wäre es eine single EXE.

Du baust also deine EXE um damit sie Packages benutzt.
Du baust dir ein Main.bpl Packages in das du alles reinpackst was Modulübergreifend gemeinsam benutzt werden soll, also Modulsystem, Hauptformular, Druckassistent usw.
Du baust nun deine Formulare in separate DLL's die weiderum mit Packages arbeiten und da sie das Package Main.bpl ebenfalls benutzen haben sie sogar noch wahlfreien und sauberen Zugriff auf die Hauptanwendung.

Nun gilt es aus deiner Sicht den Resourcenverbrauch abzuschätzen. Du musst ja nun zu deiner Anwendung auch alle Packages mit installieren die du benutzt hast. Es gibt also einen berechnenbaren Breakeven Point ab dem dein Packages basiertes Konzept nicht nur sauber sondern sogar weniger Festplattenplatz und Hauptspeicher benötigt.

Pi * Daumen:

Packages ca. 5Mb
EXE ca. 40Kb
jedes Form Modul ca. 100Kb.

Bei deiner jeztigen Lösung linkt der Compiler alles was in den Packages ist und im jeweiligen Modul benutzt wird statisch in dieses Modul ein. Ich schätze mal pro DLL Forumular kommst du so auf ca. 600Kb Größe der DLL.

Also EXE ~ 600Kb, + jedes weitere DLL Form 600Kb.

Bei 9 solchen Forms also 10 * 600 = 6.00Mb.

Mit Packages 5Mb + 80Kb + 9 Forms * 100Kb = 5.98Mb.

Also nicht nur im Resourcenverbrauch sondern auch in der Schnittstellensicherheit und Ergonomie in der Entwicklung sind Packages überlegen.

Wie baust du nun deine unterschiedlichen Formulare ?
Nicht per INI, nicht externen Form Designer oder so'n Popelkram, sondern mit Delphi. Also ganz einfach eine neue DLL erzeugt, Compileroptionen mit Packages kompilieren, deine Funktion CreateForm() exportieren, und deine Form Unit in die DLL einbinden, fertig.

Du benutz kein ShareMem da Packages benutzt werden. Du kannst auf ALLE Klassen die in Packages deklariert wurden und in den Module gemeinsam benutzt werden, ohne Probleme wie gewohnt in deinem Source zugreifen.
Du kannst aber NICHT auf diejenigen Klassen die du in den Form-DLLs deklariert hast gemeinsam zugreifen. Die sind quasi private zu den DLLs. Du kannst aber auf deren Basisklassen, solange diese in Packages deklariert wurden, wieder zugreifen.

So, ansonsten suche hier im Forum, ich habe das nämlich schon wirklich 100'erde Male erklärt ;=)

Ach übrigens, deine exportierte CreateForm() Funktion kannst du sogar noch eliminieren,sie ist nicht mehr notwendig. Wichtig ist nur das eine solche Form-DLL beim Laden der Hautanwendung mitteilt welche Formulare + Klassen in dieser DLL enthalten sind. Die geht ganz einfach indem du in der "initialization" Sektion deiner Form Unit eines Procedure RegisterForm(TMyForm) aufrufst. Der Trick dabei ist diese Procedure RegisterForm() in ads gemeinsam benutzte Package Main.bpl auszulagern. So wie RegisterClass() der VCL arbeitet kannst du nun RegisterForm() aufbauen und so in der Hauptanwendung eine Liste der erzeugbaren Formularklassen der geladenen DLL's aufbauen. Dies Liste kannst du später natürlich auch erweitern, zb. DLL Dateiname zur registrierten TForm Klasse und somit auch in eine Datei speichern. Dies ermöglicht die dann später diese Liste aus der Datei zuladen und somit bei Erzeugung einer DLL Form Klasse deren DLL vorher dynamisch zu laden. Es läuft also darauf hinaus das die DLL Form nur noch ein toter Kontainer ist der die Form Resource + die privaten Klassen + den Code zum Form enthält. Die Erzeugung eines solchen Forms liegt aber wieder in der Hand der Hauptanwendung, ergo: das Konzept der Schnittstelle ist wieder Top-Down und nicht vermischt.

Uff

Gruß Hagen

PS: ich bin Freelancer und eines meiner Verkaufsprojekte ist exakt ein solcher Frame, mit Benutzerverwaltung, dynamischer Anbindung an beliebige Datenbanken und Reportgeneratoren, mit über Komponenten konfigurierbarem Registrationssystem der Formulare in DLL's und der Veraltung des Menusystemes etc. pp. D.h. bei meinem Frame klatscht du einfach eine Komponente auf dein TForm der DLL und stellst dort alles ein was nötig ist. Diese Daten werden offline und online beim Modulssystem registriert und stehen später nachgeladen zu Verfügung um die Formulare und deren DLL's dynamisch auf Nutzeranforderung zu laden, alles ist transparent.
Und, ich verkaufe diesen Frame bzw. auch die Dienstleistung einen eigenen Frame neu zu entwicklen, cool was.
Wenn du also Interesse hast dann mail HaReddmann at T-Online dot de.
  Mit Zitat antworten Zitat
TPok

Registriert seit: 19. Jul 2004
Ort: Eisenach
25 Beiträge
 
Delphi 2005 Professional
 
#5

Re: Zugriff auf Komponenten auf einer Form in einer DLL

  Alt 28. Sep 2005, 21:32
Hallo,

danke, Hagen, für die ausführliche Erläuterung.

Ich muß den ganzen Stoff jetzt erstmal in meinem Kopf ordnen und mich in die Thematik "Packages" einlesen. Es klingt jedenfalls sehr interessant und passend für meine Problematik.
Derzeit hält sich der Umfang meine Vorhabens noch in Grenzen. Sollten die Anforderungen aber über meine Fähigkeiten steigen, komme ich gern auf dein Angebot zurück.

Liebe Grüße,
Stephan
Stephan Fietzek
  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 21:16 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