Autor Beitrag
chfue
Hält's aus hier
Beiträge: 3



BeitragVerfasst: 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:
ausblenden 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:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure StartMyDLL(myHandle: THandle); stdcall;
begin
  // Wie kann ich hier nun auf einen Button der Form1 von der Exe zugreiffen?

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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: 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 Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: 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:
ausblenden 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
  //Form kreieren
  Application.Handle := myHandle;
  FMainForm := TFrmMain.Create(Application);

  //OnClick Events des GUI zuweisen
  FMainForm.button_Close.OnClick := DoCloseForm;
  ...

  //Frames hinzufügen
  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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 75

Win XP
Delphi 7 / 8 Enterprise
BeitragVerfasst: 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:

ausblenden 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:

ausblenden 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 user profile iconNarses: Code- durch Delphi-Tags ersetzt
HelgeLange
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 735
Erhaltene Danke: 6

Windows 7
Delphi7 - Delphi XE
BeitragVerfasst: 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