Delphi - jak zapobiec przenoszeniu Forms / MsgBoxes pod poprzednim formularzem?

Wiele razy po erze Windows 98 doświadczyliśmy, że niektóre okna dialogowe tracą kolejność Z i wracają do poprzedniej formy.

Na przykład:

Dialog1.ShowModal;

Dialog1.OnClickButton() : ShowMessage('anything');

Gdy pojawia się MessageBox, czasami nie ma Fokusa i jest przenoszony pod Dialog1. Użytkownicy są zdezorientowani, mówią: moja aplikacja zamarła!!! Ale jeśli używają Alt + Tab, aby przejść do innej aplikacji iz powrotem, fokus wraca do MessageBox i będzie to okno na pierwszym planie.

Doświadczyliśmy tego z ShowMessage, MessageBox, normalne formularze, a także QuickReport formularze.

Czy ktoś o tym wie? Czy to błąd Windows? Jak możesz temu zapobiec? Jak to złapać?

Dzięki za pomoc: dd


Naprawdę powiedziałem, że po Win98, więc wszystkie OSs (również Win7) są dotknięte tym problemem. Użyliśmy Delphi 6 Prof, więc właściwości nie działają z domyślnymi formularzami.

Ktoś powiedział, że okna dialogowe komunikatów można kontrolować za pomocą MessageBox + MB_APPLMODAL. To jest dobra wiadomość, ale mamy wiele starych form i komponentów, narzędzi innych firm.

Więc jest to ciężka praca, aby zrobić zupełnie nowy wniosek z substytucją formularzy.

Ale spróbujemy to zrobić.

Myślę, że odpowiedź brzmi: jest to połowa problemu aplikacji i połowa problemu Windows. Jeśli System Windows czasami obsługuje to, a czasami nie - wydaje się to być błąd systemu Windows. Ale jeśli możemy wymusić dobre tworzenie okien modalnych, to jest to błąd programistyczny.

Czy ktoś może wyjaśnij mi, co oznacza flaga WS_POPUP? Ma jakieś skutki uboczne czy nie?

Dzięki: dd

Author: Karl Nicoll, 2010-06-08

4 answers

That ' s what the PopupMode i PopupParent właściwości są dla.

Np. możesz zrobić:

Dialog1.PopupMode := pmExplicit;
Dialog1.PopupParent := self;
Dialog1.ShowModal;

To informuje Windows o prawidłowej kolejności Z.

 15
Author: Craig Stuntz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-08 13:09:23

Dla starych wersji delphi (przed Delphi 2007), na formularzach innych niż twój główny formularz:

interface
  TMyForm = Class(TForm)
  protected
    procedure CreateParams(var Para: TCreateParams); override;
  end;
...
implementation
...
procedure TMyForm.CreateParams(var Para: TCreateParams);
begin
  inherited;
  Para.Style := Para.Style or WS_POPUP;
  { WinXP Window manager requires this for proper Z-Ordering }
  // Para.WndParent:=GetActiveWindow;
  Para.WndParent := Application.MainForm.Handle;
end;

W polach wiadomości wpisz MB_TOPMOST w swoich flagach:

Application.MessageBox(PChar(amessage), PChar(atitle),    otherflags or MB_TOPMOST);
 6
Author: Warren P,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-08 17:29:14

Patrzyłem na tę stronę i FAQ przez pół godziny i nadal nie mogę znaleźć, jak dodać komentarz, więc wybacz mi to naruszenie protokołu.

Przede wszystkim chciałbym wyjaśnić, że plakat, IMHO, nie używa Windows 98. Pisze "po epoce Windows 98" co jak rozumiem oznacza, że ma ten problem z wersjami Windows po 98.

Ponieważ też mam ten problem (CB2009), chciałbym podkreślić pytanie na plakacie " czy to błąd Windows?", którego nie widziałem odpowiedź. Jeśli jest to błąd Delphi / Builder, może istnieje sposób, aby go uniknąć? Nie widzę, jak przechwytywanie wszystkich potencjalnych okien dialogowych jest wykonalnym rozwiązaniem, ani nie unikam korzystania z fsStayOnTop. Mam formularz ustawień, który musi pozostać na moim głównym formularzu, ale formularz ustawień może i będzie wyskakujące okna dialogowe, które pod pewnymi warunkami znikną w formularzu ustawień.

Byłoby bardzo pomocne, gdybym zrozumiał, gdzie wsparcie z-order idzie źle, ponieważ może zaoferować wskazówkę, jak to zrobić unikaj tego.

 0
Author: Mike Versteeg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-09 10:49:45

Ostatnio użyłem sztuczki, aby zastosować te dwie linie kodu podczas tworzenia każdego formularza:

SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or 
  WS_EX_APPWINDOW or WS_EX_TOPMOST);
SetWindowLong(Handle, GWL_HWNDPARENT, GetDesktopWindow);

Uchwyt jest uchwytem formularza (Form1.Uchwyt). Część WS_EX_APPWINDOW sprawia, że każde okno pojawia się na pasku zadań, usuń je, jeśli nie chcesz tego dodatkowego efektu.

Dla mojej głównej formy używam tej linii:

SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or
  WS_EX_TOPMOST);

Używam również tej funkcji do tworzenia własnych okien dialogowych ( stworzyłem nową funkcję dla każdego stylu okna dialogowego-błąd, potwierdzenie, itd.):

function CustomDlg(const AMessage : string; const ADlgType: TMsgDlgType;
  const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn) : TForm;
begin
  Result := CreateMessageDialog(AMessage, ADlgType, AButtons, ADefaultButton);
  with Result do
    begin
      SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or 
        WS_EX_APPWINDOW or WS_EX_TOPMOST);
      SetWindowLong(Handle, GWL_HWNDPARENT, GetDesktopwindow);
      FormStyle := fsStayOnTop;
      BringToFront;
    end;
end;

Część FormStyle := fsStayOnTop; jest oczywiście opcjonalna, ale używam jej, aby upewnić się, że moje okna dialogowe potwierdzenia i błędów są zawsze widoczne dla użytkownika.

Wygląda to na trochę pracy, ale efekt netto jest taki, że nie muszę już martwić się o formy przypadkowo ukrywające się za innymi formami.

 0
Author: Jerry Gagnon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-31 11:24:27