| Autor |
Beitrag |
chfue
Hält's aus hier
Beiträge: 3
|
Verfasst: Di 14.07.09 12:53
Hallo zusammen
Ich habe eine Applikation mit einer MainForm. Auf dieser sind Buttons und eine Auswahlliste. Je nach Auswahl in der Liste wird eine andere DLL dynamisch geladen.
Nun würde ich gerne von der DLL auf die Form, genauer gesagt auf die Buttons zugreifen. Wie stelle ich das an?
Habe bisher folgenden Code:
Exe:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| procedure TForm1.ComboBox1Change(Sender: TObject); begin Handle := LoadLibrary(PChar('DLL Name von Combobox')); if Handle <> 0 then begin try @StartDLL := GetProcAddress(Handle, StartMyDLL); if @StartDLL <> nil then begin StartMyDLL(Application.Handle); end; finally FreeLibrary(Handle); end; end; end; |
DLL:
Delphi-Quelltext 1: 2: 3: 4: 5:
| procedure StartMyDLL(myHandle: THandle); stdcall; begin end; |
Wie kann ich hier nun auf einen Button der Form1 von der Exe zugreiffen?
Vielen Danke im Voraus für Eure Antworten.
Gruess Christian
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Di 14.07.09 13:10
Nicht direkt ...
Du hast doch schon hoffentlich den Hinweis, den Delphi in jedes DLL-Projekt einfügt, gelesen. Verstehen wäre jetzt die nächste Stufe. Dabei helf ich mal kurz: Ohne ShareMem oder ähnliche Memory-Manager können keine Objekte oder Strings zwischen verschiedenen Modulen (DLLs, EXE, ...) ausgetauscht werden. Es geht zwar schon, macht aber Probleme.
Was du aber tun kannst ist, dass Du deiner DLL einen Record mit Funktionszeigern übergibst, mit dem die ausführbaren Operationen von der DLL aus aufgerufen werden können.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
chfue 
Hält's aus hier
Beiträge: 3
|
Verfasst: Di 14.07.09 13:45
Hallo BenBe
Danke erstmals für deine schnelle Antwort.
Ich habe den FastMM4 in meiner DLL eingebunden, der sollte in etwa das gleiche bezwecken wie der ShareMem oder?
In der DLL habe ich folgendes ausprobiert:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure StartMyDLL(myHandle: THandle); stdcall; begin Application.Handle := myHandle; FMainForm := TFrmMain.Create(Application);
FMainForm.button_Close.OnClick := DoCloseForm; ...
FFrame1 := TFrame1.Create(Application); FFrame1.Parent := FMainForm.panel_main; FFrame1.Visible := true; ... end; |
Das ganze funktioniert eigentlich, nur kommt bim Start und beim Beenden der DLL eine access violation, kann aber einfach weg geklickt werden. Die Frames werden angezeigt und die Events konnten den Buttons zugeordnet werden. Nur die access violations stören auch.
Zudem scheint es so, als ob ich mit "FFrame1 := TFrame1.Create(Application);" eine neue Form kreiert habe und nicht die bestehende übernommen.
Hast du da vielleicht noch ein Tip für mich?
Danke und Gruss
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Di 14.07.09 14:06
Übergib dir das TApplication-Objekt deiner Haupt-Anwendung und such dir dann die bestehenden Form-Instanzen zusammen. So wie es jetzt ist, greifst Du nicht auf die originale Mainform zu, sondern auf eine lokale Kopie deiner DLL.
Und was hindert dich daran, dir zur Steuerung der Buttons in de Mainform einen Rekord mit Funktionspointern zu übergeben? Das wäre nicht nur portabel, sondern beseitigt eine Reihe von Problemen, die die Nutzung von Objekten über DLL-Grenzen hinweg birgt.
Wenn Du zwingend OOP über DLL-Grenzen hinweg machen willst, musst Du mit Runtime-Packages arbeiten; sowohl in der DLL, als auch in der Hauptanwendung. So besitzt sowohl die EXE als auch die DLL jeweils eine unabhängige Instanz von TApplication; mit Packages wäre dies identisch.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
P_G
      
Beiträge: 75
Win XP
Delphi 7 / 8 Enterprise
|
Verfasst: Di 14.07.09 16:37
Es gibt einen zweiten Weg: Ebenso wie eine dll kann auch eine exe Funktionen exportieren.
Du kannst in deiner Anwendung (exe) folgendes machen:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| function Button_1_Click: Boolean; stdcall; begin Form1.Button1Click(Sender); end;
exports Button_1_Click NAME 'Button_1_Click';
begin end; |
In die dll nimmst du folgendes auf:
Delphi-Quelltext 1:
| function Button_1_Click: Boolean; stdcall; external 'Meine_Exe.exe'; |
Jetzt rufts du in der dll die Funktion Button_1_Click auf. Benötigst du für die Übergabe einen String, kannst du ShareMem umgehen, indem du diesen als PChar übergibst. So weit ich weiß, ist ShareMem allerdings ohnehin seit Delphi2007 für Stringübergabe zu dlls nicht mehr notwendig.
Gruß, P_G
Moderiert von Narses: Code- durch Delphi-Tags ersetzt
|
|
HelgeLange
      
Beiträge: 735
Erhaltene Danke: 6
Windows 7
Delphi7 - Delphi XE
|
Verfasst: Di 14.07.09 17:43
Ich mache es bei meinen ERP-Komponenten anders. Link einfach RTL und VCL dynamisch hinzu, dann hast Du eine globale Instanz von Application, welche in allen von deinem Hauptprogramm geladenen DLLs verfügbar ist (da die Variable Application in der unit Forms.pas in VCL.bpl deklariert ist, glaub ich).
Application.MainForm gibt Dir zugriff auf die als Mainform deklarierte form, dann hast Du auch Zugriff auf die Buttons auf dieser Form.
@BenBE : Das mit Sharemem ist nur halbrichtig. Du kannst auf Objekte ohne weiteres zugreifen, ohne Sharemem einzubinden (oder FastMM). Es sind nur die von Delphi erzeugten Strings (die man als Variable vom Typ String deklariert), die Probleme machen. Ich nehme deshalb in records, welche ich zwischen DLLs sende, immer PChar. Allerdings mit Objekten (und deren String-Membern) ist es egal, ob Du ShareMem hast.
_________________ "Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
|
|
|