2010-06-08 17 views
13

Wiele razy po czasach Windows 98 doświadczyliśmy, że niektóre dialogi tracą kolejność Z i wracają do poprzedniej formy.Delphi - Jak zapobiegać przemieszczaniu się Forms/MsbBox pod wcześniejszym formularzem?

Na przykład:

Dialog1.ShowModal; 

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

Gdy pojawi MessageBox, to czasami nie ma ostrość i zostanie przeniesiony 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 powraca do MessageBox i będzie to okno na pierwszym planie.

Doświadczyliśmy tego dzięki ShowMessage, MessageBox, zwykłym formularzom, a także formularzom QuickReport.

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

Dzięki za pomoc: dd


naprawdę powiedział, że po Win98, więc wszystkie systemy operacyjne (także 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 wiadomości można kontrolować za pomocą MessageBox + MB_APPLMODAL. To dobra wiadomość, ale mamy wiele starych formularzy i komponentów, narzędzia firm trzecich.

Ciężka praca polega na złożeniu nowego wniosku i zastąpieniu formularzy.

Ale spróbujemy to zrobić.

Myślę, że odpowiedź brzmi: problem z połową aplikacji i połowa problemu z systemem Windows. Jeśli system Windows czasami to obsługuje, a czasem nie, wydaje się, że jest to błąd systemu Windows. Ale jeśli możemy wymusić dobre modalne tworzenie okien, to jest błąd programowania.

Czy ktoś może mi wyjaśnić, co oznacza flaga WS_POPUP? Czy ma jakiś efekt uboczny, czy nie?

podziękowań: dd

+0

Często też mam ten problem, nie znalazłem też odpowiedzi. Czekam na to, co ludzie wymyślili. –

+0

Z jaką wersją to się dzieje? –

+0

jesteś systemem Windows 98? Łał. Jak Sertac pyta, wersja Delphi jest krytyczna. Delphi 2007 i nowsze wersje mają obejście. –

Odpowiedz

13

To właśnie PopupMode and PopupParent properties są przeznaczone.

przykład można zrobić:

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

Mówi okien poprawnego Z-zamówienia.

+0

Wow, [dokumentacja na ten temat] (http://docwiki.embarcadero.com/VCL/en/Forms.TForm.PopupMode) nie jest w ogóle przydatny! Ale spróbuj; to działa! –

+1

@Craig - nie pomógłby w przypadku komunikatów ShowMessage, MessageBox i wyjątków. –

+0

@Sertac, są to funkcje wygody dotyczące zwykłych okien. Możesz tworzyć własne komunikaty o wyjątkach, posługując się 'Application.OnException'. Podobnie, jeśli potrzebujesz spersonalizowanego 'ShowMessage', możesz go napisać. –

6

Dla starszych wersji Delphi (przed Delphi 2007), w formach innych niż głównego formularza:

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; 

do skrzynek wiadomości należą MB_TOPMOST w swoich flag:

Application.MessageBox(PChar(amessage), PChar(atitle), otherflags or MB_TOPMOST); 
+0

Mam również obejście dla Dialogów utworzonych w jednostce VCL Dialogs, przed Delphi 2007. Jeśli ktoś tego potrzebuje (w wersjach sprzed 2007 roku), zadaj nowe pytanie, a ja opublikuję ten kod. –

0

Spojrzałem na ta strona i FAQ od pół godziny i nadal nie mogę znaleźć komentarza, więc wybacz mi to naruszenie protokołu.

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

Ponieważ mam również ten problem (CB2009), chciałbym podkreślić pytanie tego plakatu: "Czy to błąd Windowsa?", Na który nie widziałem odpowiedzi. Jeśli jest to błąd Delphi/Builder, być może istnieje sposób, aby tego uniknąć? Nie widzę, jak przechwytywanie wszystkich potencjalnych dialogów jest praktycznym rozwiązaniem, ani też nie należy używać fsStayOnTop. Mam formularz ustawień, który musi pozostać na górze mojego głównego formularza, ale formularz ustawień może i będzie wyświetlał okna dialogowe, które w pewnych warunkach znikną w formularzu ustawień.

Byłoby bardzo pomocne, gdybym zrozumiał, gdzie wsparcie dla z-zlecenia idzie nie tak, ponieważ może to być wskazówka, jak tego uniknąć.

+0

Jest to błąd systemu Windows, w tym sensie, że kolejność Z formularzy nie jest zachowywana przez architekturę wewnętrznego "menedżera okien" systemu Windows w systemie Windows XP po określonym punkcie. NIE jest to błąd systemu Windows, w tym sensie, że sam interfejs API Windows nie gwarantuje, że zapamięta jakąś konkretną Z-Order, która istnieje, chyba że ustawiłeś poprawnie odnośniki okna nadrzędnego za pomocą CreateParams (jak pokazałem w mojej odpowiedzi). –

+0

Nawiasem mówiąc, czy naprawdę nie widzisz żadnego tekstu (prawdopodobnie szarego) lub przycisku oznaczonego "Dodaj komentarz"? –

+0

Tak, ale tylko dla mojego własnego posta. Może ktoś może komentować inne posty tylko wtedy, gdy ma wystarczającą liczbę punktów, ale mogę wysłać odpowiedź. Nie widzę w tym logiki. Ani przyczyna tego błędu nie jest łatwa, wydaje się dość łatwa do poprawienia. –

0

Sztuczka Użyłem niedawno było zastosować te dwa wiersze kodu podczas tworzenia każdej postaci:

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

uchwyt jest uchwyt postaci (Form1.Handle). Część WS_EX_APPWINDOW powoduje, że każde okno pojawia się na pasku zadań, usuń je, jeśli nie chcesz tego dodatkowego efektu.

Na moje główne postaci używam tej linii:

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

ja również korzystać z tej funkcji, aby pomóc budować swoje własne dialogi (I stworzył nową funkcję dla każdego stylu Dialog - błędem, potwierdzenie, etc.) :

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; 

FormStyle := fsStayOnTop; część jest opcjonalna, oczywiście, ale używam go, aby upewnić się moje potwierdzenie i błędów dialogi zawsze są widoczne dla użytkownika.

Wydaje się, że to trochę pracy, ale efekt netto polega na tym, że nie muszę już martwić się o przypadkowe ukrywanie się formularzy.

+0

Należy dodać, że z funkcją 'SetWindowLong()' nie trzeba tworzyć własnych niestandardowych formularzy i można to zrobić dla wszystkich istniejących formularzy. Jeśli już tworzysz niestandardowe formularze, nadpisanie 'CreateParams()' jest drogą do zrobienia. –