Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Fenster wiederherstellen mit SetForeGround (https://www.delphipraxis.net/116144-fenster-wiederherstellen-mit-setforeground.html)

TUX_der_Pinguin 24. Jun 2008 09:48


Fenster wiederherstellen mit SetForeGround
 
Ich habe eine Anwendung geschrieben die beim 2. Aufruf des Programms eine Message an alle Fenster schickt,
bekommt die 1. Instanz der Anwendung diese Botschaft so soll das Fenster wiederhergestellt bzw. angezeigt
werden in der exakten größe was aber zur Zeit noch nicht klappt.

Wie die Message verschickt wird steht in einem anderen Beitrag von mir (Link)

Ich habe schon einige Dinge probiert und hier der letzte Versuch, das Program scheint zwar den Focus zubekommen
jedoch wird das Fenster nicht korrekt wiederhergestellt. :gruebel:

Delphi-Quellcode:
procedure TfrmMain.OnAppMsg(var Msg: TMsg; var Handled: Boolean);
begin
  Handled := False;

  if Msg.message = dwMessage then begin
    if Msg.wParam = glPrgMode then begin
      ShowWindow(Application.MainFormHandle, SW_NORMAL);
      SetForegroundWindow(Application.MainFormHandle);
    end;
    Handled := True;
  end;

end;

Luckie 24. Jun 2008 09:56

Re: Fenster wiederherstellen mit SetForeGround
 
Unter XP lässt sich ein Fenster nicht mehr so einfach in den Vordergrund bringen. Und das hat auch seinen sinn, da immer mehr Entwickler ihr Programmfenster in den Vordergrund gebracht haben, wenn irgendein Ereignis eingetreten ist und das Fenster, in dem der Benutzer gerade gearbeitet hat, seinen Eingabefokus verloren hat und auf einmal im Hintergrund war. Mich nervt so etwas tierisch. Ein einfaches Blinken in der Taskleiste reicht vollkommen, um auf etwas aufmerksam zumachen. Der Benutzer kann dann selber entscheiden, ob er weiterarbeite oder scih um das andere Fenster kümmern will.

Wenn du es aber trotzdem unbedingt so machen muss, dann guck mal hier: http://www.delphipraxis.net/internal...regroundwindow

TUX_der_Pinguin 24. Jun 2008 10:03

Re: Fenster wiederherstellen mit SetForeGround
 
Du hast da schon vollkommen recht, ich mags auch nicht wenn irgendwelche Programme meinen plötzlich irgendetwas zu machen
was sie nicht sollen, aber in Kombination mit dem Verhindern eines Mehrfach aufrufes find ich es schon sinnvoll, da der
Anwender ja genau das will also er will das Programm starten und weil es schon längst offen ist soll es halt in den
Vordergrund geholt werden, ich werd mir daher den Beitrag auf den du verwiesen hast durchlesen.

taaktaak 24. Jun 2008 10:13

Re: Fenster wiederherstellen mit SetForeGround
 
Moin, Moin,
wenn es nur darum geht, einen Mehrfachstart zu vermeiden und das ggf. bereits gestartete Programm zu aktivieren, dann gibt es doch eine andere/bessere Lösung: Normalerweise regelt man das über einen Mutex...

Luckie 24. Jun 2008 10:20

Re: Fenster wiederherstellen mit SetForeGround
 
Das hat er, denke ich mal, schon alles.

TUX_der_Pinguin 24. Jun 2008 10:21

Re: Fenster wiederherstellen mit SetForeGround
 
Zitat:

Zitat von taaktaak
Moin, Moin,
wenn es nur darum geht, einen Mehrfachstart zu vermeiden und das ggf. bereits gestartete Programm zu aktivieren, dann gibt es doch eine andere/bessere Lösung: Normalerweise regelt man das über einen Mutex...

Das Thema mehrfach Start verhindern etc. ist schon in einem anderen Beitrag abgehandelt und auch kein Problem,
das Verhindern per Mutex mache ich schon lange es ging hier nur darum das die 1. Instanz der Anwendung
wiederhergestellt wird beim erneuten aufrufen der Anwendung.

http://www.delphipraxis.net/internal...t.php?t=137264

taaktaak 24. Jun 2008 10:33

Re: Fenster wiederherstellen mit SetForeGround
 
Hmmm, seltsam.
Dann sollte es eigentlich funktionieren. Verwende ähnlichen (!) Code, allerdings in einer Unit ausgelagert - und das funktioniert bisher einwandfrei. Versuch's doch mal folgender Unit anstelle deines codes in der .dpr

Delphi-Quellcode:
unit rzM_OneInstanceOnly;

// Unit lediglich in das Projekt aufnehmen, danach werden mehrere Instanzen
// des Programmes unterbunden; bei erneutem Aufruf wird automatisch die
// erste Instanz aktiviert.

interface { ----------------------------------------------------------------- }

implementation { ------------------------------------------------------------ }

uses Forms,SysUtils,Windows;

var Mutex : THandle;
     MName : String;
     h    : HWnd;

initialization { ------------------------------------------------------------ }

  MName:=ExtractFileName(ChangeFileExt(Application.ExeName,'_MTX'));
  Mutex:=CreateMutex(nil,true,pchar(MName)); // Mutex anlegen

  if GetLastError=ERROR_ALREADY_EXISTS then begin // Fehler, Pgm schon aktiv!

    h:=0; // vorhandene Instanz suchen
    repeat
      h:=Windows.FindWindowEx(0,h,PChar('TApplication'),PChar(Application.Title))
      until h<>Application.Handle;

    if h<>0 then begin // aktivieren
      Windows.ShowWindow(h,SW_Restore);
      Windows.SetForegroundWindow(h);
      end;

    Application.Terminate; // und diesen zweiten Aufruf beenden!
    end;

finalization { -------------------------------------------------------------- }

  ReleaseMutex(Mutex); // Mutex der ersten Instanz wieder freigeben!

end.

Vjay 24. Jun 2008 10:46

Re: Fenster wiederherstellen mit SetForeGround
 
Ja der Trick könnte evtl sein aus der Zweitapplikation heraus (die ja den Fokus hat) die erste nach vorne zu holen.
Was du ja aktuell machst, ist der ersten eine Nachricht zu schicken, sie möge sich in den Vordergrund drängeln. Vielleicht sollte man das Pferd andersherum aufzäumen.

TUX_der_Pinguin 24. Jun 2008 11:27

Re: Fenster wiederherstellen mit SetForeGround
 
Ich habe das ganze jetzt am laufen, mit der Funktion "ForceForeGroundWindow" die im Beitrag den Luckie gepostet hat steht,
so wie taaktaak das gemacht hat, habe ich das früher auch so gemacht was auch alles funktioniert. Jedoch mit der aktuellen
variante das eine Windows Botschaft verschickt wird, war das Resultat das zwar das Fenster nach vorne geholt wurde jedoch nicht
mehr maximiert war, was es zuvor noch war. So müßte der Anwender jedesmal das Fenster erst wieder maximieren, mit der Funktion
ForceForeGroundWindow klappt alles wunderbar. Ich kann jetzt meine Anwendung einmal im Modus "A" und einmal im Modus "B"
starten, versuche ich den jeweiligen Modus noch mal zustarten so wird das entsprechend richtige Fenster wiederhergestellt.

Vielen dank für die Hilfe und die Tipps. :dp:

Vjay 24. Jun 2008 11:43

Re: Fenster wiederherstellen mit SetForeGround
 
Will ja nüscht sagen, aber ich hab dich im Vorthread schon auf forceForegroundWindow und die Suche verwiesen.

Also wäre der richtige Weg, der auch funktioniert, mit den Nachrichten das Handle herauszufinden und dann von der startenden Applikation die andere in den Vordergrund zu holen.

ForceForegroundWindow ist halt der unsaubere aber funktionierende Weg.

TUX_der_Pinguin 24. Jun 2008 14:09

Re: Fenster wiederherstellen mit SetForeGround
 
Zitat:

Zitat von Vjay
Will ja nüscht sagen, aber ich hab dich im Vorthread schon auf forceForegroundWindow und die Suche verwiesen.

Ja das stimmt du hast davon gesprochen, konnte jedoch ersten anlauf nichts darüber Finden. Wenn man nach diesem Begriff sucht findet DP
nichts ob wohl es Beiträge zu diesem Suchbegriff gibt.

Zitat:

Zitat von Vjay
Also wäre der richtige Weg, der auch funktioniert, mit den Nachrichten das Handle herauszufinden und dann von der startenden Applikation die andere in den Vordergrund zu holen.

Hmm... ich schicke per PostMessage(HWDN_BROADCAST,...) eine Message an alle Fenster darauf hin holt sich das Fenster selbst in den
Vordergrund, wie du das meinst müßte erstmal der Empfänger eine Botschaft zurück schicken damit ich das Handle erhalte um dann das
Fenster in den Vordergrund zuholen oder wie ?

Zitat:

Zitat von Vjay
ForceForegroundWindow ist halt der unsaubere aber funktionierende Weg.

Unsauber hört sich nicht so toll an, ich mein es funktioniert das ist korrekt, aber wäre es nicht egal ob sich ein Fenster selbst
oder von einem anderen Fenster in den Vordergrund geholt wird. Vorausgesetzt das Fenster stellt sich nicht alle nasenlang in den
Vordergrund das wäre ja wirklich nervig.

Vjay 24. Jun 2008 15:21

Re: Fenster wiederherstellen mit SetForeGround
 
Ok ich gebe zu ich habe das mit der DP-Suche jetzt nicht vorher überprüft :P

Genau so, du kannst doch der aufgerufenen Applikation eine Nachricht zurückliefern, so würde ich das mal versuchen.
Ich würde es daher unsauber nennen, da Microsoft schon dafür gesorgt hat, dass Applikationen, die nicht den Userinput-Fokus haben, sich nicht selber in den Vordergrund holen dürfen - was ich im übrigens absolut begrüsse. Ich mag selber solche Applikationen nicht, die von sich selbst überzeugt sind, dass sie unglaublich wichtig sein müssen.
Wer weiss was im nächsten OS kommt, vielleicht funktioniert forceForegroundWindow dort auch nicht mehr (hat das jemand mal in Vista getestet? :)

TUX_der_Pinguin 25. Jun 2008 08:33

Re: Fenster wiederherstellen mit SetForeGround
 
Ich werde das dann mal ausprobieren das die Anwendung eine Nachricht zurück schickt und darauf hin die 2. Instanz die
erste in den Vordergrund holt. Einen Vista Rechner habe ich zu Testzwecken hier stehen, ich glaube das ForceForeGroundWindow
sollte da auch drauf laufen bin mir nicht sicher ob ich das Gestern getestet habe als ich kurz die Anwendung unter Vista
installiert habe, der Test bezog sich generell auf die Lauffähigkeit unter Vista.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:51 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz