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/)
-   -   Modales Form finden, auf welches die Anwendung gerade wartet (https://www.delphipraxis.net/166408-modales-form-finden-auf-welches-die-anwendung-gerade-wartet.html)

DSCHUCH 12. Feb 2012 11:26

Modales Form finden, auf welches die Anwendung gerade wartet
 
Hallo,

wie schon im Thema beschrieben ist mein Ziel das Handle der Modalen Form zu ermitteln, welches gerade die Anwendung blockt. Jeder kennt sicher das problem das in bestimmten Konstellationen dieses Form in der Z-Order verschwindet, insb. wenn es keine Delphi-Form sondern zB ein Windows-Dialog ist.

Kleiner Hinweis: es kann mehrere Modale Fenster übereinander geben. Sonst wäre es ja auch zu einfach. ;)

Daniel.

Luckie 12. Feb 2012 11:30

AW: Modales Form finden, auf welches die Anwendung gerade wartet
 
Ähm du rufst es doch selber auf. Merk es dir doch einfach. Aber davon abgesehen, was willst du dann mit der Informationen machen?

himitsu 12. Feb 2012 11:39

AW: Modales Form finden, auf welches die Anwendung gerade wartet
 
Screen.ActiveForm gibt die aktive TForm zurück ... das könnte/müßte dann die aktive Modale sein.
Eventuell noch
Delphi-Quellcode:
fsModal in Screen.ActiveForm.FormState
prüfen.

Luckie 12. Feb 2012 11:41

AW: Modales Form finden, auf welches die Anwendung gerade wartet
 
Das funktioniert aber nur in einem separaten Thread, weil das modale Fenster ja den aufrufenden Thread blockiert.

jaenicke 12. Feb 2012 12:03

AW: Modales Form finden, auf welches die Anwendung gerade wartet
 
Zitat:

Zitat von Luckie (Beitrag 1150608)
Das funktioniert aber nur in einem separaten Thread, weil das modale Fenster ja den aufrufenden Thread blockiert.

Nein, es wird nur die Prozedur blockiert, aus der der Aufruf passierte. Es werden aber weiterhin Messages usw. im selben Thread verarbeitet. Man kann also problemlos in Timern oder anderen Windows Messages weiterarbeiten. (Sonst könnte das modale Fenster ja auch nicht mehr neu gezeichnet werden und würde nicht auf Eingaben reagieren können.)

Zum Thema:
In Screen.SaveFocusedList findest du die modalen Formulare wobei an Position 0 das zuletzt angezeigte steht. ;-)

Luckie 12. Feb 2012 12:10

AW: Modales Form finden, auf welches die Anwendung gerade wartet
 
Ah, OK. Klingt logisch.

DeddyH 12. Feb 2012 12:12

AW: Modales Form finden, auf welches die Anwendung gerade wartet
 
Delphi-Quellcode:
function GetModalWindow(SomeWindow: HWnd): HWnd;
var
  WindowList: TList;
  hThread: DWORD;

  function EnumFunc(aWnd: HWnd; List: lParam): Boolean; stdcall;
  begin
    if ((GetWindowLong(aWnd, GWL_EXSTYLE) and WS_EX_MDICHILD) = 0) and
       IsWindowEnabled(aWnd) and IsWindowVisible(aWnd) then
      TList(List).Add(Pointer(aWnd));
    Result := true;
  end;

begin
  Result := 0;
  if SomeWindow <> 0 then
    begin
      WindowList := TList.Create;
      try
        hThread := GetWindowThreadProcessID(SomeWindow);
        EnumThreadWindows(hThread, @EnumFunc, lParam(WindowList));
        if WindowList.Count = 1 then
          Result := HWnd(WindowList[0]);
      finally
        WindowList.Free;
      end;
    end;
end;

function IsThreadTopWindow(aWnd: HWnd): Boolean;
var
  NextWnd: HWnd;
  aThreadID, NextThreadID: DWORD;
begin
  Result := true;
  if aWnd <> 0 then
    begin
      aThreadID := GetWindowThreadProcessID(aWnd);
      NextWnd := GetWindow(aWnd, GW_HWNDPREV);
      while Result and (NextWnd <> 0) do
        begin
          NextThreadID := GetWindowThreadProcessID(NextWnd);
          if (NextThreadID = aThreadID) and IsWindowVisible(NextWnd) then
            Result := false
          else
            NextWnd := GetWindow(NextWnd, GW_HWNDPREV);
        end;
    end;
end;

function BringToForeground(aWnd: HWnd): Boolean;
const
  DRAWFLAGS = RDW_ERASE or RDW_INVALIDATE or RDW_UPDATENOW or RDW_ALLCHILDREN;
  MOVEFLAGS = SWP_NOMOVE or SWP_NOSIZE;
  SHOWMOVEFLAGS = MOVEFLAGS or SWP_SHOWWINDOW;
begin
  Result := true;
  if (aWnd <> 0) and IsWindowVisible(aWnd) then
    begin
      Result := SetWindowPos(aWnd, HWND_TOPMOST, 0, 0, 0, 0, MOVEFLAGS) and
                SetWindowPos(aWnd, HWND_NOTOPMOST, 0, 0, 0, 0, MOVEFLAGS) and
                SetWindowPos(aWnd, HWND_TOP, 0, 0, 0, 0, SHOWMOVEFLAGS);
      if Result then
        RedrawWindow(aWnd, nil, 0, DRAWFLAGS);
    end;
end;
Damit klappt das (bislang) auch bei fremden Anwendungen. Für die eigene wäre so etwas denkbar (Prozedur ist Applicaton.OnIdle zugewiesen):
Delphi-Quellcode:
procedure TFrmMain.DoOnIdle(Sender: TObject; var Done: Boolean);
var
  ModalWnd: HWnd;
begin
  ModalWnd := GetModalWindow(Handle);
  if (ModalWnd <> 0) and not IsThreadTopWindow(ModalWnd) then
    BringToForeground(ModalWnd);
  Done := true;
end;

DSCHUCH 12. Feb 2012 12:14

AW: Modales Form finden, auf welches die Anwendung gerade wartet
 
nimm einfach eine exception an, die ruft man nicht selbst auf. oder zb dialoge vom dbnavigator. etc.

modale formen durchlaufen nutzt nix, da gibt es ja mehrere. ich weiß trotzdem nicht welches die ist, welche gerade die aktive sein sollte.

wenn ich nach diesem thread gehe, könnte man es finden indem man zusätzlich auf enabled prüft:
http://www.delphipraxis.net/159994-t...-anzeigen.html

bestimmte modale dialogforms verschwinden immerwieder hinter fsStayOnTop Forms. das nervt gewaltig...

beobachten kann man dies allerdings in diversen delphiapplications. so zB auch der speichern-dialog im finalbuilder, der is auch manchmal einfach hinter dem hauptfenster und man kann nur noch mit trick 17 arbeiten.

Zitat:

Screen.SaveFocusedList
schaue ich mir gleich mal an.

Zitat:

DeddyH.....
ebenso, danke - damit habe ich sicher erstmal paar stunden zu testen.

DSCHUCH 12. Feb 2012 12:32

AW: Modales Form finden, auf welches die Anwendung gerade wartet
 
Liste der Anhänge anzeigen (Anzahl: 2)
ich habe hier mal ein bsp zusammengeklickt, funktioniert aber in dem kleinen bsp nur mit eurekalog.

der dialog, welchen eurekalog öffnet liegt hier im hintergrund. man kann diesen schön hinter die TopMostForm schieben, dann geht nur noch mit tastaturbedienung irgendwas zu machen.
man kann das in diesem fall umgehen, indem man den dialog mittels options auch als stayontop erstellen läßt, aber andere dialoge haben zT gleiche effekte.

daniel.


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