Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Fenster einer DLL in den Vordergrund (https://www.delphipraxis.net/56964-fenster-einer-dll-den-vordergrund.html)

Moony 14. Nov 2005 11:27


Fenster einer DLL in den Vordergrund
 
Hallo zusammen!

Habe das Problem, dass ich aus meiner Applikation aus in einer bestimmten Routine eine DLL starte. In der Applikation ist ein weiteres Fenster geöffnet und wird somit als inaktives Fenster gekennzeichnet. Alles schön und gut. Jetzt wird in der DLL ein anderes Fenster geöffnet und hier ist das Problem. Das Fenster ist zwar aktiv, aber es läßt sich nicht mit den Befehlen "BringToFront()" oder "SetForeGroundWindow()" in den Vordergrund setzen. Ebenso ist das bei Messages die dann im Hintergrund sind. :wall:
Ich hoffe mir kann da jemand weiterehelfen.

Gruß, moony

etom291272 14. Nov 2005 13:02

Re: Fenster einer DLL in den Vordergrund
 
poste bitte mal den code der dll wo das fenster erzeugt und angezeigt wird

Moony 14. Nov 2005 13:44

Re: Fenster einer DLL in den Vordergrund
 
Die DLL wird statisch aus der Applikation aus aufgerufen und nach Rückgabe des Wertes direkt wieder freigegeben:

Delphi-Quellcode:
function DLLLaden(dllname, functionname: String):Boolean;stdcall;export;
type Tcustfunction=function (var Names,Values:pchar):boolean;stdcall;

var cfunction : tcustfunction;
    custhdl  : Thandle;
    Func     : TFarProc;
begin
  ...
  custhdl := LoadLibrary(PChar(extractfilepath(application.exename) + dllname));
  custfunc := GetProcAddress(custhdl,pchar(functionname));
  if custfunc <> nil then
  begin
    @cfunction := custfunc;
    result:=true;
  end
  else begin
    result := false;
    FreeLibrary(custhdl);
    exit;
  end;
  result := cfunction(...,...);
  FreeLibrary(custhdl);
  ...
end;
Das Fenster wird ja dann normal mit dem Laden der DLL erzeugt. Aufgerufen wird das Fenster hier:

Delphi-Quellcode:
Procedure DLL.FormShow();
begin
  ...
  Fenster.ShowModal;
  if Fenster.ModalResult := mrCancel then Exit;
  ...
end;
dann...
Delphi-Quellcode:
Procedure Fenster.FormShow();
begin
  Fenster.BringToFront;
end;
Ich hoffe das kann dir weiterhelfen. Das sind die wichtigsten Aufrufe.

gruß, moony

chaosben 14. Nov 2005 14:07

Re: Fenster einer DLL in den Vordergrund
 
Nach meinem Wissensstand muss ich dich leider enttäuschen: So geht es nicht. Scheinbar liegt es daran, das das Eltern-Fenster sein "neues Kind" nicht als VCL-Fenster anerkennt und es deshalb auch nicht so behandelt. Du könntest eventuell versuche, das Kind-Fenster als Objekt zu übergeben und es von den Eltern erzeugen zu lassen (wie das in Natur ebenfalls gemacht wird :stupid: )

Moony 14. Nov 2005 14:36

Re: Fenster einer DLL in den Vordergrund
 
Verstehe ich nich! :gruebel:

Es wird doch in der Applikation Fenster1 über ShowModal geöffnet. Während das Fenster1 gezeigt wird, wird von der Applikation eine DLL statisch geladen. In der DLL wird das Fenster2 als Übergang aufgerufen. In diesem Fenster2 wird ein weiteres Fenster3 aufgerufen. Das kann doch nicht so schwer sein die Fenster aus der DLL in den Vordergrund bringen zu können. Fenster1 hat ja überhaupt keine Ahnung davon dass es Fenster2 & Fenster3 gibt.

tigerman33 14. Nov 2005 14:39

Re: Fenster einer DLL in den Vordergrund
 
Vielleicht kann ich ja nur nicht richtig lesen, aber wo wird in dem Code denn überhaupt das Fenster erzeugt?

Moony 14. Nov 2005 14:51

Re: Fenster einer DLL in den Vordergrund
 
Die Fenster von der Applikation werden beim Starten der Applikation unter

Delphi-Quellcode:
begin
  ...
  Applikation.CreateFrom(TFenster1, Fenster1);
  ...
end.
erstellt.

Die Fenster werden von der DLL unter

Delphi-Quellcode:
begin
  ...
  Applikation.CreateFrom(TFenster2, Fenster2);
  Applikation.CreateFrom(TFenster3, Fenster3);
  ...
end.
erstellt.

Also wird das Erstellen der Formen von der Applikation und DLL selbst übernommen.

tigerman33 14. Nov 2005 18:28

Re: Fenster einer DLL in den Vordergrund
 
Du schreibst, die DLL wäre statisch eingebunden. Trotzdem lädst du sie mit LoadLibrary und gibst sie sogar anschließend wieder frei. Eins von beidem geht doch aber nur.

Wo genau ist der Aufruf, der das Fenster anzeigen soll? Passiert das in irgendeiner Art und Weise in der cfunction?

Ianisp 15. Nov 2005 14:54

Re: Fenster einer DLL in den Vordergrund
 
Hallo Moony,

Du kannst deiner Funktion den Application Handle übergeben:

Delphi-Quellcode:
type Tcustfunction=function (AHandle: THandle; var Names,Values:pchar):boolean;stdcall;
Der Aufruf aus der Anwendung sollte so aussehen:

Delphi-Quellcode:
result := cfunction(Application.Handle,...,...);
In der DLL die Funktion custfunction ändern:

Delphi-Quellcode:
Application.Handle := AHandle;
hoffe, das hilft dir weiter.

Gruß, Ianis

tigerman33 15. Nov 2005 18:21

Re: Fenster einer DLL in den Vordergrund
 
Hast du es eigentlich schonmal mit Form2.Perform versucht? Ihm also quasi eine Message "vorgegaukelt"?

Moony 18. Nov 2005 08:38

Re: Fenster einer DLL in den Vordergrund
 
Also,

@tigerman:
wenn du das so siehst, dann wird die DLL dynamisch eingebunden.
Ich versuche das ganze Verfahren noch mal zu erläutern: Das Fenster1, welches im Vordergrund bleibt, wird irgendwann von der Applikation aus mit Show() aufgerufen. Im weiteren Verlauf, also solange das Fenster1 noch gezeigt wird, wird dann die DLL geladen. In der DLL wird über ein Hilfsfenster Fenster2 (ist uninteressant) das Fenster3 in der Fenster2.FormShow() über die Funktion Fenster3.ShowModal() aufgerufen. Nun wird in der Funktion Fenster3.OnShow() dieses Fenster in den Vordergrund gestellt mit Fenster3.BrintToFront(). Aber das macht er nicht!
Alle Fenster werden jeweils in den DPR-Files zu Beginn erstellt mit Application.CreateFrom(TForm, Form).

Als zusätzliche Info: Das passiert ja nicht nur bei Fenstern. Auch wenn ich in einer DLL eine Message ausgebe ist diese dann auch im Hintergrund und man denkt die Applikation ist abgeschmiert, weil ja nichts passiert. Die Message aber ist hinter dem Fenster1.

@Ianis:
Die Sache mit der Handleübergabe funktioniert auch nicht. :(

gruß, moony

tigerman33 18. Nov 2005 11:20

Re: Fenster einer DLL in den Vordergrund
 
Sehr rätselhaft. Hast du schonmal probiert Fenster2 und/oder Fenster3 nicht automatisch am Anfang erzeugen zu lassen, sondern von Hand, dynamisch zu erzeugen?

Zitat:

Das Fenster1, welches im Vordergrund bleibt, wird irgendwann von der Applikation aus mit Show() aufgerufen.
Interpretier ich das richtig, dass Fenster1 immer im Vordergrund sein soll? Dann könnte ich mir vorstellen, dass die Fenster 2 und 3 sich nicht zu der Anwendung "zugehörig" fühlen, und deshalb vom Fenster1 verdeckt werden. Das müsste sich lösen lassen, wenn du die Forms dynamisch in der DLL erstellst, denke ich.

Moony 18. Nov 2005 13:02

Re: Fenster einer DLL in den Vordergrund
 
Fenster2 ist ja total irrelevant, da dieses Fenster nur Mittel zum Zweck ist und dort verwendete KADAO Komponenten gelagert werden. Fenster3 wird ja in der Fenster2.OnShow aufgerufen. Dort habe ich auch versucht dann erst Fenster3 mit

Delphi-Quellcode:
Fenster3 := TFenster3.Create(Fenster3);
zu erstellen und bei der Fenster3.OnClose() das Fenster wieder mit

Delphi-Quellcode:
Fenster3.Release;
freizugeben. Aber irgendwie will mich hier jemand ärgern. Wie gesagt, das Problem besteht nicht nur bei Fenstern sondern auch bei popeligen Showmessages. Die lassen sich auch nicht in den Vordergrund setzen!

Ich glaub das ist hoffnungslos.... :cry:


Was dein Verständnis von Fenster1 betrifft, NEIN das Fenster soll nicht im Vordergrund bleiben. Das ist ja mein Problem. Es bleibt nämlich im Vordergrund, obwohl das Fenster ja in diesem Moment inaktiv ist.

tigerman33 18. Nov 2005 14:38

Re: Fenster einer DLL in den Vordergrund
 
Es würde helfen, wenn du nochmal ein bisschen mehr vom Code posten würdest. Vor allem dem, was in der DLL steht.

Moony 19. Nov 2005 12:57

Re: Fenster einer DLL in den Vordergrund
 
So wirklich viel mehr bringt es nicht zu posten, da das Programm bereits zu komplex aufgebaut ist und viel zu viele Ereignisse durchgeführt werden. Aber ich versuche es ein wenig übersichtlicher zu gestalten:

In der Applikation sieht das ganze so aus:

In der Projektdatei werden die Formulare erstellt:
Delphi-Quellcode:
Projekt.dpr

uses
...

begin
  Application.Initialize;
  ...
  // Erstellung des Fenster1 zur Laufzeit
  Application.CreateForm(TFenster1, Fenster1);
  ...
  Application.Run;
end.
Anschließend wird beim klicken auf eine Schaltfläche das Fenster1 aufgerufen:
Delphi-Quellcode:
unit Applikation;
...

procedure Schaltfläche.OnClick();
type TmyFunc = function :boolean;stdcall;

var CustFunc : TFarProc;
    CustHdl : THandle;
    myFunc  : TmyFunc;
    DllName,
    Funktion : String;
begin
  ...
  // Das Fenster der Applikation wird geöffnet
  Fenster1.Show;
  ...
  // Dynamischer Aufruf der DLL
  CustHdl := LoadLibrary(PChar(extractfilepath(application.exename) + DLLName));
  CustFunc := GetProcAddress(CustHdl, PChar(Function));
  if CustFunc <> nil then
  begin
    @myFunc := CustFunc;
    Result := myFunc;
  end;
  // DLL wieder freigeben
  FreeLibrary(CustHdl);
end;
Innerhalb der DLL wird dann folgendermaßen verfahren:

Delphi-Quellcode:
library DLLName;

uses
  ...

begin
  Application.initialize;
  Application.CreateForm(TFenster2, Fenster2);
  Application.CreateForm(TFenster3, Fenster3);
end.
Innerhalb der geladenen DLL wird das Hauptfenster Fenster2 geöffnet. Hier wird in der Prozedur Fenster2.FormShow() der folgende Aufruf getätigt:

Delphi-Quellcode:
unit Fenster2;

...

procedure Fenster2.FormShow();
begin
  ...
  Fenster3.ShowModal;
  if Fenster3.ModalResult = mrCancel then
    Exit;
  ...
end;
Anschließend wird in der Prozedur Fenster3.FormShow() der folgende Aufruf gesetzt:

Delphi-Quellcode:
unit Fenster3;

...

procedure Fenster3.FormShow();
begin
  Fenster3.BringToFront;
end;
So ist der Stand wie zu Anfang beschrieben. Jedoch bringt das ja nicht.
Habe ebenfalls versucht die Fenster2/3 dynamisch zu erstellen, das hat aber auch nichts gebracht. Ich hatte zuerst gedacht das geht, aber nach der nächsten Kompillierung wurden alle Fenster wieder hinter Fenster1 gesetzt.

Showmessages zeigen den gleichen Effekt wie Fenster2 & 3, nämlich dass sie hinter dem Fenster1 bleiben und nicht im Vordergrund gezeigt werden können. Sehr blöd, wenn die Message kleiner als das Fenster1 ist.

So, hoffe jetzt ist das übersichtlicher und eine Lösung findet sich.

gruß, moony

tigerman33 19. Nov 2005 13:56

Re: Fenster einer DLL in den Vordergrund
 
Steht die Application-Variable denn innerhalb einer DLL überhaupt zur Verfügung? Die DLL könnte ja von mehreren Anwendungen gleichzeitig benutzt werden, auf welche davon verweist dann Application? Ich vermute mal, dass die DLL eine eigene Application-Variable hat. Wenn hierfür nun Fenster erstellt werden und deine Haupt-Anwendung gerade den Fokus hat, sind diese DLL-Fenster natürlich im Hintergrund.

Versuch doch mal, die Fenster explizit in einer Prozedur zu erstellen, der du die Application-Variable der Hauptanwendung übergibst. Mit dieser erstellst du dann die Fenster. (Oder du machst es gleich mit TFenster2.Create(Fenster1) )

Funktioniert das?

Moony 21. Nov 2005 08:12

Re: Fenster einer DLL in den Vordergrund
 
Zitat:

Steht die Application-Variable denn innerhalb einer DLL überhaupt zur Verfügung?
Natürlich steht sie zur Verfügung, denn für die DLL selbst ist das eine eigenständige Applikation. Diese weiß ja überhaupt nichts von einer anderen Anwendung.


Zitat:

Die DLL könnte ja von mehreren Anwendungen gleichzeitig benutzt werden
Wenn die DLL von mehreren Anwendungen benutzt werden würde, dann käme es zu einer Zugriffsverletzung. Davon abgesehen ist das bei mir nicht der Fall.


Zitat:

auf welche davon verweist dann Application
Die erste Application-Variable in der Projekt.dpr ist die Hauptanwendung. die zweite in der Library DLLName ist die Applikation der DLL.


Zitat:

Versuch doch mal, die Fenster explizit in einer Prozedur zu erstellen, der du die Application-Variable der Hauptanwendung übergibst. Mit dieser erstellst du dann die Fenster.
Ich kann doch die Application-Variable nicht übergeben, da die Hauptanwendung in der DLL überhaupt nicht bekannt ist. Das heißt, dass die DLL nichts davon weiß, dass sie von einer Anwendung aufgerufen wird.
Eigenständig erstellt hab ich diese auch, hat aber recht wenig genutzt. Zumindest hat er das beim ersten Kompillieren nach vorne gesetzt und bei jedem weiteren nicht mehr.


Zitat:

Oder du machst es gleich mit TFenster2.Create(Fenster1)
Das kann ich nicht machen, weil ich in der DLL keinen Zugriff auf Fenster1 habe, da dieses in der Hauptanwendung existiert.


Das ist doch alles nicht wahr. :wall:
Es muß doch eine Möglichkeit geben diese dämlichen Fenster in den Vordergrund zu setzen. Und vor allem kann es ja nicht an dem Aufruf der Fenster liegen, weil normale Showmessages ebenfalls im Hintergrund bleiben!

tigerman33 21. Nov 2005 11:33

Re: Fenster einer DLL in den Vordergrund
 
Du hast mich ein wenig falsch verstanden.

Dass das gleichzeitige Benutzen einer DLL durch mehrere Programme eine Schutzverletzung zur Folge haben soll ist mir neu. Wieso sollte das so sein?

Dass die Application-Variable innerhalb der DLL eine andere ist als innerhalb der Applikation hatte ich vermutet (die meisten meiner Fragen waren eher rethorischer Natur). Deswegen ja auch mein Vorschlag:

Delphi-Quellcode:
// In der DLL:
procedure CreateFenster(const AnAplication: TApplication);
begin
  AnApplication.CreateForm (TFenster2, Fenster2);
  AnApplication.CreateForm (TFenster3, Fenster3);
end;

// Dann Aufruf aus dem Hauptprogramm:
CreateFenster (Application);
Das ist untested, aber ich erhoffe mir davon, dass es das Problem löst, da die beiden Fenster von der Anwendung erzeugt werden, die auch tatsächlich gerade den Fokus hat, und nicht von der DLL selbst.

Moony 14. Dez 2005 11:12

Re: Fenster einer DLL in den Vordergrund
 
Hallo,

hab das jetzt anders gelöst. die Form, welche in der ersten Applikation immer im Vordergrund ist, war auf StayOnTop gesetzt. Es hatte auch einen bestimmten Grund, aber ich habs jetzt entfernt.

Danke für alles.

Gruß, Moony


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:15 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