Le formulaire est caché derrière d'autres formulaires lorsque ShowModal est appelé

StackOverflow https://stackoverflow.com/questions/1639125

  •  08-07-2019
  •  | 
  •  

Question

Mon application est basée sur des formulaires modaux. Le formulaire principal ouvre un formulaire avec ShowModal, ce formulaire en ouvre un autre avec ShowModal. Nous avons donc empilé des formulaires modaux. Il arrive parfois que lorsque nous appelons ShowModal sous une nouvelle forme, celui-ci se cache derrière les formulaires précédents, au lieu de s'afficher en haut. Après avoir appuyé sur alt + tab, la forme revient en haut, mais ce n'est pas une bonne solution. Avez-vous rencontré ce problème et comment l'avez-vous géré?

MODIFIER :

J'utilise Delphi 7.

Était-ce utile?

La solution

Vous n'avez pas mentionné quelle version de Delphi ...

Les versions les plus récentes de Delphi ont ajouté deux nouvelles propriétés à TCustomForm: PopupMode et PopupParent. Définir PopupParent de votre boîte de dialogue modale sur le formulaire qui crée cette boîte de dialogue garantit que le formulaire enfant reste au-dessus de son parent. Cela résout généralement le problème que vous décrivez.

Je pense que cette paire de propriétés a été ajoutée à Delphi 2006, mais c'était peut-être en 2005. Elles sont définitivement présentes dans Delphi 2007 et les versions ultérieures.

EDIT: Après avoir constaté que vous utilisiez Delphi 7, la seule suggestion que je puisse vous donner est la suivante: dans le code qui affiche votre formulaire modal, vous désactivez le formulaire le créant et réactivez-le à son retour. Cela devrait empêcher la fenêtre de création de recevoir des entrées, ce qui peut aider à maintenir l'ordre Z correct.

Quelque chose comme cela pourrait fonctionner (non testé, car je n'utilise plus de 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;

Si Form2 crée une fenêtre modale (comme vous l'avez mentionné), répétez simplement le processus: désactivez Form2, créez Form3 et affichez-le sous forme modale, puis réactivez Form2 à son retour. Assurez-vous d’utiliser try..finally comme je l’ai montré, afin que, en cas de problème avec le formulaire modal, le formulaire de création soit toujours réactivé.

Autres conseils

Désolé d’ajouter une réponse distincte, mais j’ai fait un peu plus de recherches et certaines d’entre elles indiquent que ma réponse précédente (DisableProcessWindowsGhosting) n’aide en rien. Comme je ne peux pas toujours reproduire ce problème, je ne peux pas le dire avec certitude.

J'ai trouvé une solution qui semble appropriée. J'ai référencé le code dans Delphi 2007 pour la méthode CreateParams et il correspond assez bien (sans avoir tout le code qui gère PopupMode).

J'ai créé l'unité au-dessous des sous-classes 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;

Ce que je fais alors est d'inclure cette unité dans une unité de formulaire, puis de changer la classe du formulaire (dans le fichier de code .pas) de classe (TForm) en classe (TModalForm )

Cela fonctionne pour moi, semble être proche de la solution CodeGear.

De ce lien , il semble que le problème soit lié à la " Fenêtre fantôme " cela a été introduit en 2000 / XP. Vous pouvez désactiver cette fonctionnalité en appelant le code suivant au démarrage.

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

Le seul problème que je vois est que cela causera des problèmes avec la fonctionnalité qui permet à l'utilisateur de minimiser, déplacer ou fermer la fenêtre principale d'une application qui ne répond pas . De cette manière, vous ne devez pas couvrir chaque appel avec le code Self.Enabled: = False .

Définissez simplement la propriété Visible du formulaire que vous souhaitez ouvrir en mode modal sur False . Ensuite, vous pouvez l'ouvrir avec .ShowModal (); et cela fonctionnera.

l'essayer OnShowForm:

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

J'ai constaté que l'utilisation de l'option "Toujours au premier plan" drapeau sur plus d'une forme provoque des problèmes avec l'ordre Z. Et vous pouvez également trouver le besoin de Fonction BringWindowToTop .

Lors du lancement d'une boîte de message à l'aide de l'interface WinAPI intégrée ( MessageBox ), j'ai constaté qu'il était nécessaire de passer le handle de la fenêtre appelante pour s'assurer que l'invite apparaît en haut de tous les temps.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top