2009-10-28 7 views
19

Moja aplikacja oparta jest na formularzach modalnych. Główna forma otwiera jedną formę z ShowModal, ta forma otwiera kolejną z ShowModal, więc mamy ułożone formularze modalne. Czasami pojawia się problem polegający na tym, że kiedy wywołujemy ShowModal w nowej formie, ukrywa się on za wcześniejszymi formularzami, zamiast pokazywać na wierzchu. Po naciśnięciu klawisza alt + formularz wraca na górę, ale nie jest to dobre rozwiązanie. Czy spotkałeś się z tym problemem i jak sobie z tym poradziłeś?Formularz jest ukryty za innymi formularzami, gdy program ShowModal jest nazywany

EDIT:

używam Delphi 7.

+0

Dzięki za dodanie wersji. Pomaga, jeśli umieścisz to w tekście lub tekście twojego pytania. :-) –

+0

Najpierw ustawiłem odpowiednią etykietę, potem dodałem EDIT :) – LukLed

+0

Tak długo, jak gdzieś to umieścisz, działa. Nie musi koniecznie znajdować się w jednym z tagów, o ile jest w temacie lub w tekście pytania. Dzięki temu ludzie wiedzą, jaką masz funkcjonalność, gdy odpowiadają. :-) –

Odpowiedz

20

Nie wspominając która wersja Delphi ...

Nowsze wersje Delphi zostały dodane dwa nowe właściwości TCustomForm: PopupMode i PopupParent. Ustawienie PopupParent okna dialogowego modalnego na formularz, który tworzy to okno dialogowe, zapewnia, że ​​formularz podrzędny pozostaje na jego rodzica. Zwykle rozwiązuje problem, który opisujesz.

Myślę, że ta para właściwości została dodana w Delphi 2006, ale mogło to być 2005. Są zdecydowanie w Delphi 2007 i wyżej.

EDYCJA: Po zobaczeniu, że używasz Delphi 7, jedyną sugestią jaką mam, jest to, że w kodzie, który wyświetla twoją formę modalną, wyłącza się tworzenie formularza i ponownie włącza po powrocie. To powinno uniemożliwić utworzenie okna wprowadzania danych, co może pomóc w utrzymaniu porządku Z.

Coś takiego może działać (niesprawdzone, a ja już nie używam D7):

procedure TForm1.ShowForm2; 
begin 
    Self.Enabled := False; 
    try 
    with TForm2.Create(nil) do 
    begin 
     try 
     if ShowModal = mrOk then 
      // Returned OK. Do something; 
     finally 
     Free; 
     end; 
    end; 
    finally 
    Self.Enabled := True; 
    end; 
end; 

Jeśli Form2 tworzy okno modalne (jak już wspomniano), po prostu powtórzyć proces - wyłączyć Form2 , utwórz Form3 i pokaż go modalnie, a następnie ponownie włącz Form2 po jego powrocie. Upewnij się, że użyłeś try..finally, tak jak to pokazałem, więc jeśli coś pójdzie nie tak w formie modalnej, formularz tworzenia jest zawsze ponownie włączony.

+0

Przepraszam, to jest Delphi 7. Nie ma PopupMode i PopupParent, ale czy dobrze jest wiedzieć, że one istnieją. – LukLed

+0

Mogę wypróbować to rozwiązanie, ale w projekcie mamy wiele formularzy modalnych, skrzynki wiadomości są modalne, więc czasami może być trudne do wdrożenia. Ale spróbuję to zrobić, jeśli to możliwe. – LukLed

+0

To działało dla mnie przy użyciu Self.Enabled: = Fałsz; and Self.Enabled: = True; –

-1

I odkryli, że za pomocą "Zawsze na wierzchu" flagę na więcej niż jednej postaci powoduje problemy z zamówieniem Z. Możesz również znaleźć potrzebę funkcji BringWindowToTop.

Po uruchomieniu okna komunikatu przy użyciu wbudowanego interfejsu WinAPI (MessageBox), stwierdziłem, że podanie uchwytu okna wywoływania jest konieczne, aby upewnić się, że monit jest cały czas wyświetlany na górze.

+1

Zobacz moją odpowiedź na Lars D. Właściciel (lub Rodzic) nie mają nic wspólnego z opisywanym problemem. Problem polega na usunięciu ukrytego okna TAppication z paska zadań; spowodował problem z formularzami podrzędnymi, które utraciły swoje właściwe miejsce w kolejności Z, co zostało stworzone, aby naprawić PopupParent i PopupMode. –

+0

Wystarczająco uczciwe ... podczas dalszej inspekcji, zdaję sobie sprawę, że myślałem o użyciu funkcji Windows.MessageBox i przekazywaniu uchwytu okna wywoływania, aby upewnić się, że MessageBox pojawia się na wierzchu wywołującego - który rozważałem jako rodzic". Zmienię moją odpowiedź, aby to odzwierciedlić. –

2

Z tego link wynika, że ​​problem dotyczy "okna Ghosting", które zostało wprowadzone w 2000/XP. Możesz wyłączyć funkcję maskowania, wywołując następujący kod podczas uruchamiania.

procedure DisableProcessWindowsGhosting; 
var 
    DisableProcessWindowsGhostingProc: procedure; 
begin 
    DisableProcessWindowsGhostingProc := GetProcAddress(
    GetModuleHandle('user32.dll'), 
    'DisableProcessWindowsGhosting'); 
    if Assigned(DisableProcessWindowsGhostingProc) then 
    DisableProcessWindowsGhostingProc; 
end; 

Jedyny problem, że widzę to, że będzie to powodować problemy z funkcją, która umożliwia użytkownikowi na minimize, move, or close the main window of an application that is not responding. Ale w ten sposób nie musisz pokrywać każdego połączenia kodem Self.Enabled := False.

+0

Jeśli to naprawdę działa, byłoby wspaniale. Dziękuję Ci. Ten problem dręczy mnie przez bardzo długi czas. To, co mnie intryguje, brzmi: "Jeśli jednak formularz miał styl WS_POPUP, a" właściciel "był poprawnym oknem, nawet forma" widmowa "nie pozwoliłaby na zmianę Z-porządku na jego właściciela, więc nie ma szansy na modalne okno dialogowe, które nagle znika. ". Nie widziałem żadnego odniesienia do jednostki Owner in Forms. – LukLed

4

Przepraszamy za dodanie oddzielnej odpowiedzi, ale zrobiłem trochę więcej badań, a niektóre z nich wskazują, że moja poprzednia odpowiedź (DisableProcessWindowsGhosting) nie pomaga. Ponieważ nie zawsze mogę odtworzyć ten problem, nie mogę powiedzieć na pewno.

Znalazłem rozwiązanie, które wydaje się odpowiednie. Odwołuję się do kodu w Delphi 2007 dla metody CreateParams i pasuje całkiem blisko (bez całego kodu obsługującego PopupMode).

Utworzono jednostkę, poniżej której znajdują się podklasy TForm.

unit uModalForms; 

interface 

uses Forms, Controls, Windows; 
type 
    TModalForm = class(TForm) 
    protected 
    procedure CreateParams(var params: TCreateParams); override; 
    end; 

implementation 

procedure TModalForm.CreateParams(var params: TCreateParams); 
begin 
    inherited; 

    params.WndParent := Screen.ActiveForm.Handle; 

    if (params.WndParent <> 0) and (IsIconic(params.WndParent) 
    or not IsWindowVisible(params.WndParent) 
    or not IsWindowEnabled(params.WndParent)) then 
    params.WndParent := 0; 

    if params.WndParent = 0 then 
    params.WndParent := Application.Handle; 
end; 

Co zrobić, wtedy jest to urządzenie się z jednostki formularz, a następnie zmienić klasę postaci (w pliku kodu .pas) z class(TForm) do class(TModalForm)

To działa dla mnie, wydaje się być blisko rozwiązania CodeGear.

+0

Spróbuję najpierw z DisableProcessWindowsGhosting i sprawdzę, czy działa. Potem na to popatrzę. Dzięki. – LukLed

+0

działa idealnie - dzięki Jimowi – tomo7

1

Wystarczy ustawić właściwość formularza Visible, że chcesz otworzyć modalnego, aby False. Następnie możesz go otworzyć przy pomocy .ShowModal(); i to zadziała.

0

spróbować go OnShowForm:

+1

6 lat za późno, ale dzięki :) – LukLed