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 Ich krieg mein Fenster nicht automatisch aktiv. (https://www.delphipraxis.net/207121-ich-krieg-mein-fenster-nicht-automatisch-aktiv.html)

t2000 25. Feb 2021 16:19

Ich krieg mein Fenster nicht automatisch aktiv.
 
Hi zusammen,

ich hoffe, hier reicht ein kleine Hilfe.

Folgende Situation
VCL 64bit Windows
Das Delphi Main Formular soll (erstnmal) ohne Funktion im Hintergrund sein.
Ich möchte ein weiteres Formular sofort nach dem Start öffnen und AKTIV haben.
Ich sehe das, weil die FensterTitelBar im inaktiven Zustand eine andere Farbe hat und sich leider einige Komponenten erst bei Aktivierung korrekt zeichnen.

DPR-Quelltext:

Erzeugen, Anzeigen Splash
Create Delphi-Mainform (frmDesktop)

Delphi-Quellcode:
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  //Application.MainFormOnTaskbar := False;
  frmSplash := TfrmSplash.Create(nil);
  frmSplash.Show;
  Application.CreateForm(TfrmDesktop, frmDesktop);
  Application.Run;
Dann in der frmDesktop:

Da ich den Splashscreen solange stehen haben möchte, bis wirklich alles fertig ist, habe ich die das ApplicationIdleEvent genutzt.
Dort erzeuge ich dann die eigentlichen Mainform und möchte sie anzeigen/aktivieren

Delphi-Quellcode:
procedure TfrmDesktop.ApplicationEventsIdle(Sender: TObject; var Done: Boolean);
begin
  if frmSplash <> nil then begin
    SystemInit;
    FfrmMain := TfrmMain.Create( self);
    FfrmMain.Init;
    FfrmMain.Show;
    FfrmMain.SetFocus;
    FfrmMain.btnHomeClick(nil);
    FreeAndNil( frmSplash);
//    FfrmMain.btnHomeClick(nil);
//    SetForegroundWindow( FfrmMain.Handle);
//    FfrmMain.SetFocus;
  end;
Ihr seht, das ich hier schon einiges ausprobiert habe.

Das Fenster erscheint (im Vollbildmodus), ist aber nicht aktiv. Erst wenn ich dann manuell mit der Maus klicke, wird das Fenster aktiviert. (Sichtbar durch Anpassung der FensterTitelFarbe)

Was mache ich falsch? Wie geht es besser?

Gruß
Thomas

himitsu 25. Feb 2021 16:29

AW: Ich krieg mein Fenster nicht automatisch aktiv.
 
Windows lässt standardmäßig nicht mehr zu, dass sich irgendein Hintergrund-Programm selbst in den Vordergrund holt (außer auf Interaktion mit dem Benutzer, wenn er klickt)

* das aktive Programm kann deinem Programm das Recht geben sowas machen zu dürfen
* ...


siehe Remarks: MSDN-Library durchsuchenSetForegroundWindow
Such einfach mal Forum ... da gibt es schon viele Threads zu, teilweise auch mit "Lösungen"

Der schöne Günther 25. Feb 2021 16:51

AW: Ich krieg mein Fenster nicht automatisch aktiv.
 
Tipp: Manchmal ist es wirklich die IDE (oder ein IDE-Plugin) welches sich gewaltsam den Fokus holt obwohl dein Programm es eigentlich hätte. Besteht das Problem auch wenn du deine Anwendung "ganz normal" (also nicht über die IDE, auch ohne Debugging) startest?

mytbo 25. Feb 2021 16:51

AW: Ich krieg mein Fenster nicht automatisch aktiv.
 
Ich weis nicht, ob ich deine Anforderungen richtig verstanden habe. Hier meine Interpretation:

Unit frm_Splash.pas
Delphi-Quellcode:
procedure ShowSplash;
begin
  if not Assigned(frmSplash) then
    frmSplash := TfrmSplash.Create(Application);

  frmSplash.Show;
  frmSplash.Update
end;

procedure CloseSplash;
begin
  FreeAndNil(frmSplash);
end;
*.dpr Datei
Delphi-Quellcode:
  ShowSplash;
  Application.Initialize;
  Application.CreateForm(TfrmMain, frmMain);
Unit frm_Main.pas
Delphi-Quellcode:
procedure TfrmMain.FormShow(Sender: TObject);
begin
  PostMessage(Handle, WM_SETUPAPPLICATION, 0, 0);
end;

procedure TfrmMain.WMSetupApplication(var pmvMessage: TMessage);
begin
  CloseSplash;
end;
Bis bald...
Thomas

t2000 25. Feb 2021 17:07

AW: Ich krieg mein Fenster nicht automatisch aktiv.
 
@himitsu
Gesucht ja, aber nicht viel gefunden. Die Lösungen aus 2007 funktionieren nicht "ForceForegroudWindow"

@Der schöne Günther
Ja, auch wenn ich es extern starte.

@mytbo
Nein, so nicht. Es geht nicht um den Splashscreen. Den kann man komplett weg lassen. Ich erzeugt ein Form (frmDesktop) und von dort aus ein weiteres Form frmMain. Ich zeige dies und es ist nicht aktiv.

Ich dachte, wenn ich aus einer Anwendung/Form eine neue Form erzeuge und öffne/zeige, dann sollte diese auch aktiv sein. Ist ja nicht so,das ich im Hintergrund etwas mache. Bzw. machen will

t2000 25. Feb 2021 17:11

AW: Ich krieg mein Fenster nicht automatisch aktiv.
 
Sollte dies alleine nicht reichen, um ein Formular zu erzeugen, zu zeigen und dort aktiv zu sein? Also auch den Eingabefokus zu erhalten?

Delphi-Quellcode:
// ich bin in einer beliebigen Form und mache von dort:
    FfrmMain := TfrmMain.Create( self);
    FfrmMain.Show;

himitsu 25. Feb 2021 17:23

AW: Ich krieg mein Fenster nicht automatisch aktiv.
 
Zitat:

Zitat von t2000 (Beitrag 1483846)
Ist ja nicht so,das ich im Hintergrund etwas mache. Bzw. machen will

Dein Programm ist/war ja im Hintergrund (hatte keinen Eingabefokus) und daher verweigert Windows ihm sich selbstständig den Vordergrund zu setzen.

Wenn man ein Programm neu startet, dann war der Andere (Desktop/Explorer/Startmenü/...) vorher altiv und somit kann ein neues Programm auch sofort aktiv werden. (ist eine der Bedingungen, wie sie im SetForegroundWindow aufgzählt werden)


Ich weiß auch grade nicht wo, aber es wurden auch schonmal irgendwelche "Tricks" genannt, welche womöglich noch funktionieren.

t2000 25. Feb 2021 17:36

AW: Ich krieg mein Fenster nicht automatisch aktiv.
 
Warum ist/war mein Programm im Hintergrund?

Ich glaube, ich verstehe hier etws nicht.
Auch die Win-Doku sagt doch:
Zitat:

Remarks

The system restricts which processes can set the foreground window. A process can set the foreground window only if one of the following conditions is true:

The process is the foreground process.
The process was started by the foreground process.
- Explorer aktiv
- ich starte mein Programm
- Mein Programm aktiv mit Main-Fenster
- Ich erzeuge/öffne ein neues Fenster

Warum sollte dieses neue Fenster nicht aktiv sein?
Wo hab ich den Denkfehler?

mytbo 25. Feb 2021 17:50

AW: Ich krieg mein Fenster nicht automatisch aktiv.
 
Zitat:

Zitat von t2000 (Beitrag 1483851)
- Explorer aktiv
- ich starte mein Programm
- Mein Programm aktiv mit Main-Fenster
- Ich erzeuge/öffne ein neues Fenster

Warum sollte dieses neue Fenster nicht aktiv sein?
Wo hab ich den Denkfehler?

Also hiermit ist ClientForm bei mir aktiv:
Delphi-Quellcode:
procedure TfrmMain.FormShow(Sender: TObject);
begin
  PostMessage(Handle, WM_SETUPAPPLICATION, 0, 0);
end;

procedure TfrmMain.WMSetupApplication(var pmvMessage: TMessage);
begin
  FClientForm := TfrmClient.Create(Self);
  FClientForm.Show;
end;
Bis bald...
Thomas

Rolf Frei 25. Feb 2021 17:57

AW: Ich krieg mein Fenster nicht automatisch aktiv.
 
Warum machst du es nicht einfach so im DPR:

Delphi-Quellcode:
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  //Application.MainFormOnTaskbar := False;
  frmSplash := TfrmSplash.Create(nil);
  try
    frmSplash.Show;
    Application.CreateForm(TfrmDesktop, frmDesktop);
  finally
    frmSplash.Free;
  end;
  Application.Run;

t2000 25. Feb 2021 18:11

AW: Ich krieg mein Fenster nicht automatisch aktiv.
 
Vergesst doch mal den blöden Splash Screen. Daum geht es doch gar nicht.

Den lösche ich erst später da StyOnTop stehen bleiben soll, bis der Bildschirm komplett sichtbar ist. Das funktioniert auch alles sehr gut.

Es geht darum, direkt nach dem Start aus dem Delphi-Main-Form, welches auch noch bis zum Programmende genutzt werden soll, ein NEUES Fenster geöffnet werden soll. Und dieses zweite Fenster soll das Eingangsfenster für den Anwender sein. Und das möchte ich aktiv haben.

mytbo 25. Feb 2021 18:16

AW: Ich krieg mein Fenster nicht automatisch aktiv.
 
Zitat:

Zitat von t2000 (Beitrag 1483856)

Es geht darum, direkt nach dem Start aus dem Delphi-Main-Form, welches auch noch bis zum Programmende genutzt werden soll, ein NEUES Fenster geöffnet werden soll. Und dieses zweite Fenster soll das Eingangsfenster für den Anwender sein. Und das möchte ich aktiv haben.

Mein letzter Vorschlag macht das doch, zumindest bei mir.

Bis bald...
Thomas

t2000 25. Feb 2021 18:22

AW: Ich krieg mein Fenster nicht automatisch aktiv.
 
Zitat:

Zitat von mytbo (Beitrag 1483852)
Also hiermit ist ClientForm bei mir aktiv:
Delphi-Quellcode:
procedure TfrmMain.FormShow(Sender: TObject);
begin
  PostMessage(Handle, WM_SETUPAPPLICATION, 0, 0);
end;

procedure TfrmMain.WMSetupApplication(var pmvMessage: TMessage);
begin
  FClientForm := TfrmClient.Create(Self);
  FClientForm.Show;
end;
Bis bald...
Thomas

Das ist nicht in Ordnung, weil FormShow sehr früh aufgerufen wird. Bevor das Fenster sichtbar ist.
Ich starte
Splash kommt
Desktop-Form kommt
... jetzt laufen die ganzen Inits .. das dauert ein wenig ...
MainForm wird gezeigt (also die zweite Form)
und der Splash verschwindet.

Am Bildschirm ist jetzrt die DesktopForm (die erste Form, Delphi-MainForm) sichtbar, aber im Hintergrund
Im Fordergrund ist die zweite Form, meine persönliche MainForm
Leider nicht aktiv, was zu optischen Unschönheiten führt, die ich gerne beseitigen möchte.
Ich könnte (siehe erstes Posting) an der Stelle, an der ich den Splash schließe ein Postmessage machen. Aber da vermute ich keinerlei Änderung. Was ist "WM_SETUPAPPLICATION". Ich finde nichts im Internet darüber.

t2000 25. Feb 2021 18:43

AW: Ich krieg mein Fenster nicht automatisch aktiv.
 
Der Focus wird mir geklaut.

In einem Testprogramm warte ich über einen Timer etwas. Also so das ALLE Dinge abgeschlossen sind. Dann geht es.

Ich muss also eine Lösung finden, das wirklich ALLE create/show/activate vom "frmDesktop" (Delphi-MainForm) abgeschlossen ist.
ERST DANN darf ich das neue Fenster erzeugen.

Wahrscheinlich ein erneutes "OnIdle" programmieren.

t2000 25. Feb 2021 19:01

AW: Ich krieg mein Fenster nicht automatisch aktiv.
 
Gelöst!

Es hat nichts mit WinAPI Sperre oder ähnlichem zu tun.

Wenn ich mittels Timer eine Sekunde nach dem frmMain.Show warte, dann funktioniert alles.

Es könnte schon mit dem Splash zusammenhängen. Schließe ich den Splash zur falschen Zeit, bekomme ich das Fenster nicht aktiv. Die falsche Zeit ist genau in dem Moment, zwischen dem Focuswechsel von Form 1 zu Form 2.
Ohne das jetzt im Detail zu testen. Mit dem Timer geht alles.

t2000 25. Feb 2021 19:05

AW: Ich krieg mein Fenster nicht automatisch aktiv.
 
Einzige Änderung: Der Timer, der den Splash verzögert schließt.

Wenn mir jemand die Gründe erklären könnte, wäre ich sehr dankbar.

Delphi-Quellcode:
procedure TfrmDesktop.ApplicationEventsIdle(Sender: TObject; var Done: Boolean);
begin
  if frmSplash <> nil then begin
    SystemInit;
    FfrmMain := TfrmMain.Create( self);
    FfrmMain.Init;
    FfrmMain.Show;
    TimerSplash.Enabled := True;
  end;
end;

procedure TfrmDesktop.TimerSplashTimer(Sender: TObject);
begin
  TimerSplash.Enabled := False;
  FreeAndNil( frmSplash);
end;

himitsu 25. Feb 2021 19:14

AW: Ich krieg mein Fenster nicht automatisch aktiv.
 
Du kannst im Delphi mal ein paar Events loggen.
Screen.OnActiveControlChange/OnActiveFormChange
Application.xxx bzw. ApplicationEvents.OnActivate/OnDeactivate/OnRestore/OnModalBegin/OnModalEnd

Dann siehst'e wann/wo dein Fokus hin geht,
bzw. ein Haltepunkt, wenn er am verschwinden ist und dann im Debugger gucken von wo es ausgelöst wurde.

Beim Schließen von Delphi-Fenstern versucht an einigen Stellen die VCL den Fokus zurückzusetzen (lässt nicht Windows entscheiden wohin er geht).
Nimmst sich die VCL dann ein HWND für's MSDN-Library durchsuchenSetFocus, welches aber nicht mehr existiert, dann schmeißt Windows das Programm in den Hintergrund. (das wurde übrigens auch im SetForegroundWindow erwähnt)

Passiert z.B. gern, wenn man ein Fenster anzeigt, während oder kurz bevor ein anderes Fenster geschlossen wird.
Noch schöner, wenn man z.B. im OnClose ein ShowMessage oder ShowModal macht, denn Delphi hängt den Dialog ans aktuell aktive Fenster, aber Dieses verschwindet ja grade und es nimmt dabei auch gleich den Dialog mit ins Nirvana. :freak:



Sobald dein Programm einmal den Fokus verloren hat und er auf ein anderes Programm übergehen konnte (wenn Deines nicht das einzige sichtbare Programm ist), dann kann dein Programm sich den Fokus nicht selbstständig zurückholen. (außer zufällig trifft eine der erwähnten Bedingenen von SetForegroundWindow zu)


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