Soru ShowModal çağrıldığında Form diğer formların arkasında gizlidir.


Uygulamam kalıcı formlara dayanıyor. Ana form, ShowModal ile bir form açar, bu form ShowModal ile başka bir açılır, bu yüzden modal formları yığarız. Bazen ShowModal'ı yeni formda aradığımızda, üstte göstermek yerine, önceki formların arkasına gizlenen bir problem vardır. Alt + sekmesine bastıktan sonra, form üste gelir, ancak bu iyi bir çözüm değildir. Bu problemle tanıştın mı ve nasıl hallettin?

DÜZENLE:

Ben Delphi 7'yi kullanıyorum.


21
2017-10-28 18:20


Menşei


Versiyonu eklediğiniz için teşekkürler. Sorunuzun metnine veya etiketlerine bir yer eklerseniz size yardımcı olur. :-) - Ken White
İlk önce uygun etiketi ayarladıktan sonra DÜZENLE ekledim :) - LukLed
Bir yere koyduğun sürece işe yarıyor. Sorunun konusu ya da metninde olduğu sürece etiketlerden birinde olması zorunlu değildir. Bu, insanlara, cevap verdiklerinde sizin için hangi işlevselliğe sahip olduğunuzu bilmelerini sağlar. :-) - Ken White
Yıllardır üçüncü taraf uygulamasıyla bu sorunu yaşadık ve henüz bir düzeltme bulunamadı. - Paul-Sebastian Manole


Cevaplar:


Delphi'nin hangi versiyonundan bahsetmedin ...

Yeni Delphi sürümleri, TCustomForm: PopupMode ve PopupParent'e iki yeni özellik ekledi. Modal iletişim kutusunun PopupParent değerini, bu iletişim kutusunu oluşturan formata ayarlamak, alt formun üst öğenin üst kısmında kaldığından emin olur. Genellikle tanımladığınız sorunu giderir.

Bu özelliklerin Delphi 2006'da eklendiğini düşünüyorum, ancak 2005 olabilirdi. Kesinlikle Delphi 2007'de ve üstte.

DÜZENLEME: Delphi 7'yi kullandığınızı gördükten sonra sahip olduğum tek öneri, modal formunuzu görüntüleyen kodda, onu oluşturan formu devre dışı bırakmanız ve dönüşte yeniden etkinleştirmenizdir. Bu, oluşturma penceresinin Z sırasını doğru tutmaya yardımcı olabilecek giriş almasını engellemelidir.

Böyle bir şey işe yarayabilir (artık D7'yi kullanmadığım için denenmemiş):

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;

Form2 bir modal penceresi oluşturuyorsa (belirtmiş olduğunuz gibi), yalnızca işlemi tekrarlayın - Form2'yi devre dışı bırakın, Form3'ü oluşturun ve bunu otomatik olarak gösterin ve döndüğünde Form2'yi yeniden etkinleştirin. Try..finally'i kullandığım gibi kullandığınızdan emin olun, böylece modal formda bir şeyler ters giderse, oluşturma formu her zaman yeniden etkinleştirilir.


21
2017-10-28 19:02



Üzgünüz, bu Delphi 7'dir. PopupMode ve PopupParent yoktur, ancak var olduklarını bilmek iyidir. - LukLed
Bu çözümü deneyebilirim, ancak projede çok fazla modal formumuz var, mesaj kutuları modal, bu yüzden uygulanması zor olabilir. Ama bunu mümkün olduğunca yapmaya çalışacağım. - LukLed
Self.Enabled kullanarak benim için çalıştı: = False; ve Self.Enabled: = Doğru; - Jordi Corbilla
Ben, PopupParent çözüm Delphi XE2 bir tedavi çalışır teyit edebilirim, çok teşekkürler! - Duncan
@Duncan: Size yardımcı olduysa cevabımı destekleyerek teşekkürlerinizi iletebilirsiniz. :-) - Ken White


Ayrı bir cevap eklemek için özür dilerim, ama biraz daha fazla araştırma yaptım ve bir kısmı da önceki yanıtımın (DisableProcessWindowsGhosting) yardımcı olmadığını gösteriyor. Bu konuyu her zaman yeniden üretemediğimden emin olamıyorum.

Uygun görünen bir çözüm buldum. CreateParams yöntemi için Delphi 2007'deki kodu başvuruyordum ve oldukça yakın (PopupMode'u işleyen diğer kodun tamamı olmadan) eşleşiyor.

Alt sınıfı hangi birim altından oluşturdum 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;

Yaptığım şey, bu birimi bir form birimine dahil et ve sonra formun sınıfını (.pas kodu dosyasında) class(TForm) için class(TModalForm)

Benim için çalışıyor, CodeGear'ın çözümüne yakın görünüyor.


6
2017-11-19 19:37



Önce DisableProcessWindowsGhosting ile deneyeceğim ve çalışıp çalışmadığını kontrol edeceğim. Sonra buna bakacağım. Teşekkürler. - LukLed
Mükemmel çalışıyor - teşekkürler Jim - tomo7


Bundan bağlantı Problemin 2000 / XP'de tanıtılan "Ghosting penceresi" ile olduğu anlaşılıyor. Başlangıçta aşağıdaki kodu arayarak gölgelenme özelliğini devre dışı bırakabilirsiniz.

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

Görebildiğim tek sorun, kullanıcıya izin veren özellikte sorunlara neden olmasıdır. Yanıt vermeyen bir uygulamanın ana penceresini simge durumuna küçültme, taşıma veya kapatma. Ancak bu şekilde her aramayı Self.Enabled := False kodu.


2
2017-11-18 19:07



Gerçekten işe yarıyorsa, harika olurdu. Teşekkür ederim. Bu problem beni çok uzun bir süre için rahatsız ediyor. Bana ilgi çekici olan şey 'Ancak, form WS_POPUP stiline sahipse ve "sahip" doğru pencereyse, "hayalet" bir form bile Z siparişini sahibinin altına geçirmesine izin verilmez. aniden kaybolmak için kalıcı bir iletişim kutusu. Forms biriminde Sahibine herhangi bir başvuru görmedim. - LukLed


Sadece ayarla Visible modal açmak istediğiniz formun özelliği False. Sonra açabilirsiniz .ShowModal(); ve işe yarayacak.


1
2017-10-20 09:40





dene OnShowForm:

PostMessage(Self.Handle, WM_USER_SET_FOCUS_AT_START, 0, 0);

0
2017-07-08 06:45



6 yıl çok geç ama teşekkürler :) - LukLed


Birden fazla formdaki "Always On Top" bayrağını kullanmanın Z sırası ile ilgili sorunlara neden olduğunu buldum. Ve aynı zamanda BringWindowToTop işlevi.

Yerleşik WinAPI'yi kullanarak bir mesaj kutusu başlatırken (MessageBox), Komut isteminin her zaman üstte göründüğünden emin olmak için arama penceresinin tutamacını geçmenin gerekli olduğunu buldum.


-1
2017-10-28 18:50



Lars D. Owner'a (veya Anne) yanıtımın açıklanmakta olan sorunla ilgisi olmadığını görün. Sorun, TAppication'ın Gizli Penceresinin Görev Çubuğundan kaldırılmasının bir sonrası etkisidir; Çocukların formları, Z-düzeninde uygun yerlerini kaybederek, PopupParent ve PopupMode'un düzeltmek için yarattıkları soruna neden oldu. - Ken White
Yeterince adil ... Daha fazla incelemede, Windows.MessageBox işlevini kullanmayı düşündüğümü ve MessageBox'un arayanın üst kısmında görünmesini sağlamak için arama penceresinin tanıtıcısını geçirdiğimi fark ettim. "ana". Cevabımı bunu yansıtacak şekilde düzenler. - Scott W