ShowModal := 1 ne ferme pas la fenêtre modale !

ShowModal := 1 ne ferme pas la fenêtre modale ! - Delphi/Pascal - Programmation

Marsh Posté le 06-11-2007 à 13:57:21    

Bonjour à tous :)
 
Ca fait un moment (trois jours exactement) que je plante sur une question de fenêtre modale.  
 
Appel de la fenêtre, depuis Form1:
   Form3.ShowModal;
 
Ca marche, elle s'affiche. Son code exécute ce qu'il a à faire, mais parfois il doit rendre la main à la Form1. Et là, bingo :kaola: ! L'instruction Form3.ModalResult := 1 ne referme rien du tout... Il me faut cliquer sur le bouton "Quitter" de la form3 ! Et là, la même instruction marche !!
 
Je m'y perds, là  :pt1cable: Je passe à côté de quoi :heink: ?  
 
P.S./ j'ai cherché sur Google, ds l'aide de Delphi, j'ai essayé Close, etc... rien !
 
 :pfff:  
 
Merci pour toute aide :hello:


Message édité par HERIBERT le 06-11-2007 à 13:57:36
Reply

Marsh Posté le 06-11-2007 à 13:57:21   

Reply

Marsh Posté le 09-11-2007 à 12:43:30    

question con : tu ne surcharge pas la méthode "Close"? Rien de spécial non plus dans le "onclose"? Y a t-il des instruction suivant l'affectation(car ce n'est pas l'affectation à proprement parler qui ferme le formulaire)?
 


---------------
Si vous êtes enseignant en maternelle ou primaire, mon boulot peut vous interesser.
Reply

Marsh Posté le 09-11-2007 à 13:06:47    

el zozo a écrit :

question con : tu ne surcharge pas la méthode "Close"? Rien de spécial non plus dans le "onclose"? Y a t-il des instruction suivant l'affectation(car ce n'est pas l'affectation à proprement parler qui ferme le formulaire)?
 


Question pas con du tout :non: Je n'y avais pas même pensé.
 
Je vais regarder tout ça :heink:

Reply

Marsh Posté le 09-11-2007 à 18:53:10    

el zozo a écrit :

question con : tu ne surcharge pas la méthode "Close"? Rien de spécial non plus dans le "onclose"? Y a t-il des instruction suivant l'affectation(car ce n'est pas l'affectation à proprement parler qui ferme le formulaire)?
 


Eh ! non...
 
Je trente de revenir à la fenêtre appelante par : Form3.ModalResult := 1;
 
Cette fenêtre Form3 concerne la sauvegarde et le traitement des paramètres de FireFox et Thunderbird, ainsi que leurs plugins, les caches, etc. Au niveau des path, tout est correct.  
 
Je n'ai pas écti d'autre code pour la fermer. Mais j'ai bien sûr essaué Close. Rien à faire :??:

Reply

Marsh Posté le 09-11-2007 à 20:33:36    

HERIBERT a écrit :

Question pas con du tout :non:


Je t'avouerais que c'était un demi-euphemisme. Faut bien considéré que t'a peut-être fait une bourde grosse comme moi (et c'est pas peut dire  :cry: )
 
Par exemple, affiche-tu bien la fenêtre par le code "Form3.ShowModal" et non par un code du genre
 

With TForm3.create do
  ShowModal
end;


 
Auquel cas, la variable Form3 ne désigne pas la fenêtre afficher.
 
Si le code est un peu touffu, surveiller la valeur de Form3.visible juste avant d'affecter "ModalValue" pourrait être instructif.


---------------
Si vous êtes enseignant en maternelle ou primaire, mon boulot peut vous interesser.
Reply

Marsh Posté le 10-11-2007 à 00:23:05    

showmodal est bloquant
il attend que la fenetre soit fermée et retourne la valeur de "modalresult" (qui doit etre spécifier la fenetre elle meme)

Reply

Marsh Posté le 10-11-2007 à 12:22:27    

KangOl a écrit :

showmodal est bloquant
il attend que la fenetre soit fermée et retourne la valeur de "modalresult" (qui doit etre spécifier la fenetre elle meme)


exact... a 80%. Ca ne bloque que l'execution de la procédure appelé.
 

form3.showmodal;
beep;
form3.modalValue := 1;


Ne fermera pas la fenetre (et ne bipera pas)
En fait, "Bloquer" n'est pas le terme approprié. Les instruction s'exécute séquentiellement, et la procedure ShowModal prend le temps qu'il faut pour s'achever(avec la fermeture de la fenetre, donc)
 
 
Mais ça ne bloque pas la fenetre ouvrante en elle même.
Si tu met un timer dans la fenetre ouvrant avec

TForm1.OnTimer
begin
  Form3.ModalValue := 1;
end;


Ca fermera bien la fenetre modale


Message édité par el zozo le 10-11-2007 à 12:32:35

---------------
Si vous êtes enseignant en maternelle ou primaire, mon boulot peut vous interesser.
Reply

Marsh Posté le 10-11-2007 à 14:34:07    

la magie des threads...

Reply

Marsh Posté le 10-11-2007 à 15:18:03    

En fait, c'était surtout pour critiquer ce passage là qui peut prêter à confusion.

KangOl a écrit :

il attend que la fenetre soit fermée et retourne la valeur de "modalresult" (qui doit etre spécifier par la fenetre elle meme)


Evidemment, à moins de faire un truc tordu comme dans mon exemple, la fenêtre appelante ne peut pas fermer la fenêtre modale. Mais le ModalResult n'a pas de propriété magique qui l'obligerais à n'être appeler que depuis sa propre fenêtre. Si la fenêtre modale Form3 appelle une procédure quelconque contenant le code "form3.modalResult := 1", ça marche très bien.  
Le critère n'est pas de savoir d' l'instruction est exécuté, mais uniquement si elle est exécutée (et évidement de savoir si la fenêtre affichée est bien l'objet Form3)
Enfin... en théorie. Il semble que notre ami HERIBERT soit tombé sur un cas tordu.  [:alph-one]

Message cité 1 fois
Message édité par el zozo le 10-11-2007 à 15:18:23

---------------
Si vous êtes enseignant en maternelle ou primaire, mon boulot peut vous interesser.
Reply

Marsh Posté le 10-11-2007 à 15:29:42    

el zozo a écrit :

En fait, c'était surtout pour critiquer ce passage là qui peut prêter à confusion.


 

el zozo a écrit :


Evidemment, à moins de faire un truc tordu comme dans mon exemple, la fenêtre appelante ne peut pas fermer la fenêtre modale. Mais le ModalResult n'a pas de propriété magique qui l'obligerais à n'être appeler que depuis sa propre fenêtre. Si la fenêtre modale Form3 appelle une procédure quelconque contenant le code "form3.modalResult := 1", ça marche très bien.  
Le critère n'est pas de savoir d' l'instruction est exécuté, mais uniquement si elle est exécutée (et évidement de savoir si la fenêtre affichée est bien l'objet Form3)
Enfin... en théorie. Il semble que notre ami HERIBERT soit tombé sur un cas tordu.  [:alph-one]


 
 
"(...) Enfin... en théorie. Il semble que notre ami HERIBERT soit tombé sur un cas tordu " : C'est le moins que l'on puisse dire :D !  
 
Je crois que je vais passer carrément par un Createprocess() . C'est comme ça que j'avais fait pr la version précédente. Les autres fenêtres modales me posent moins de pb :spookie:  
 
Avec CreateProcesss () , ce sera radical : Application.Terminate; Et boum !

Reply

Marsh Posté le 10-11-2007 à 15:29:42   

Reply

Marsh Posté le 10-11-2007 à 15:44:18    

Reply

Marsh Posté le 10-11-2007 à 15:52:08    


+1  :lol: :D
 
Avant de déclencher logiciellement le reset du BIOS, a tu au moins mis un point d'arrêt sur la ligne "form3.modalValue=1" pour d'assurer que ton code passe bien par là.
A-tu aussi testé la valeur de "Form3.visible" pour vérifier que c'est bien cette variable là qui s'affiche à l'écran (et non une autre occurrence de TForm3)


---------------
Si vous êtes enseignant en maternelle ou primaire, mon boulot peut vous interesser.
Reply

Marsh Posté le 30-11-2007 à 10:27:53    

Bonjour,
 
J’arrive un peu tard dans la conversation mais comme on dit « vieux motard que jamais ! »
J’ai aussi eu ce problème à résoudre : vouloir fermer un formulaire modal lors de l’ouverture de ce dernier. Pour cela on écrit la commande Close ou on affecte une valeur à ModalResult dans l’un des évènements disponibles du TForm ; soit OnActivate ou OnShow. Et là : CA MARCHE PAS !
Il s’agit en fait d’un bug de la VCL. Si vous regardez le source de la procédure TForm.ShowModal vous vous rendez compte que le formulaire va rester ouvert tant que ModalResult = 0 ou que l’on ferme l’application. Hors dans cette procédure, ModalResult prend la valeur zéro après l’exécution de tous les évènements à notre disposition : cela revient à annuler notre action de fermeture.
Pour pallier à cela, il faut réécrire la procédure ShowModal dans notre formulaire modal.
 
En voici le source écrit avec Delphi 7 :
 


type
  TForm2 = class(TForm)
    procedure FormActivate(Sender: TObject);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }
    procedure CloseModal;
    function ShowModal: Integer;  reintroduce;
  end;
 
...
 
function TForm2.ShowModal: Integer;
var
  WindowList: Pointer;
  SaveFocusCount: TFocusState;
  SaveCursor: TCursor;
  ActiveWindow: HWnd;
begin
  CancelDrag;
  if Visible or not Enabled or (fsModal in FFormState) or
    (FormStyle = fsMDIChild) then
    raise EInvalidOperation.Create(SCannotShowModal);
  if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0);
  ReleaseCapture;
  Application.ModalStarted;
  try
  Include(FFormState, fsModal);
  ActiveWindow := GetActiveWindow;
  SaveFocusCount := SaveFocusState;
  SaveCursor := Screen.Cursor;
  Screen.Cursor := crDefault;
  WindowList := DisableTaskWindows(0);
  try
    ModalResult := 0; // ligne du bug déplacée ici
    Show;
    try
      SendMessage(Handle, CM_ACTIVATE, 0, 0);
      repeat
        Application.HandleMessage;
        if Application.Terminated then ModalResult := mrCancel else
          if ModalResult <> 0 then CloseModal;
      until ModalResult <> 0;
      Result := ModalResult;
      SendMessage(Handle, CM_DEACTIVATE, 0, 0);
      if GetActiveWindow <> Handle then ActiveWindow := 0;
    finally
      Hide;
    end;
  finally
    Screen.Cursor := SaveCursor;
    EnableTaskWindows(WindowList);
    if ActiveWindow <> 0 then SetActiveWindow(ActiveWindow);
    RestoreFocusState(SaveFocusCount);
    Exclude(FFormState, fsModal);
  end;
  finally
    Application.ModalFinished;
  end;
end;
 
procedure TForm2.CloseModal;
var
  CloseAction: TCloseAction;
begin
  try
    CloseAction := caNone;
    if CloseQuery then
    begin
      CloseAction := caHide;
      DoClose(CloseAction);
    end;
    case CloseAction of
      caNone: ModalResult := 0;
      caFree: Release;
    end;
  except
    ModalResult := 0;
    Application.HandleException(Self);
  end;
end;
 
procedure TForm2.FormActivate(Sender: TObject);
begin
  self.close;
end;

Reply

Marsh Posté le 30-11-2007 à 10:40:16    

lfi a écrit :

Bonjour,
 
J’arrive un peu tard dans la conversation mais comme on dit « vieux motard que jamais ! »
J’ai aussi eu ce problème à résoudre : vouloir fermer un formulaire modal lors de l’ouverture de ce dernier. Pour cela on écrit la commande Close ou on affecte une valeur à ModalResult dans l’un des évènements disponibles du TForm ; soit OnActivate ou OnShow. Et là : CA MARCHE PAS !
Il s’agit en fait d’un bug de la VCL. Si vous regardez le source de la procédure TForm.ShowModal vous vous rendez compte que le formulaire va rester ouvert tant que ModalResult = 0 ou que l’on ferme l’application. Hors dans cette procédure, ModalResult prend la valeur zéro après l’exécution de tous les évènements à notre disposition : cela revient à annuler notre action de fermeture.
Pour pallier à cela, il faut réécrire la procédure ShowModal dans notre formulaire modal.
 
En voici le source écrit avec Delphi 7 :
 


type
  TForm2 = class(TForm)
    procedure FormActivate(Sender: TObject);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }
    procedure CloseModal;
    function ShowModal: Integer;  reintroduce;
  end;
 
...
 
function TForm2.ShowModal: Integer;
var
  WindowList: Pointer;
  SaveFocusCount: TFocusState;
  SaveCursor: TCursor;
  ActiveWindow: HWnd;
begin
  CancelDrag;
  if Visible or not Enabled or (fsModal in FFormState) or
    (FormStyle = fsMDIChild) then
    raise EInvalidOperation.Create(SCannotShowModal);
  if GetCapture <> 0 then SendMessage(GetCapture, WM_CANCELMODE, 0, 0);
  ReleaseCapture;
  Application.ModalStarted;
  try
  Include(FFormState, fsModal);
  ActiveWindow := GetActiveWindow;
  SaveFocusCount := SaveFocusState;
  SaveCursor := Screen.Cursor;
  Screen.Cursor := crDefault;
  WindowList := DisableTaskWindows(0);
  try
    ModalResult := 0; // ligne du bug déplacée ici
    Show;
    try
      SendMessage(Handle, CM_ACTIVATE, 0, 0);
      repeat
        Application.HandleMessage;
        if Application.Terminated then ModalResult := mrCancel else
          if ModalResult <> 0 then CloseModal;
      until ModalResult <> 0;
      Result := ModalResult;
      SendMessage(Handle, CM_DEACTIVATE, 0, 0);
      if GetActiveWindow <> Handle then ActiveWindow := 0;
    finally
      Hide;
    end;
  finally
    Screen.Cursor := SaveCursor;
    EnableTaskWindows(WindowList);
    if ActiveWindow <> 0 then SetActiveWindow(ActiveWindow);
    RestoreFocusState(SaveFocusCount);
    Exclude(FFormState, fsModal);
  end;
  finally
    Application.ModalFinished;
  end;
end;
 
procedure TForm2.CloseModal;
var
  CloseAction: TCloseAction;
begin
  try
    CloseAction := caNone;
    if CloseQuery then
    begin
      CloseAction := caHide;
      DoClose(CloseAction);
    end;
    case CloseAction of
      caNone: ModalResult := 0;
      caFree: Release;
    end;
  except
    ModalResult := 0;
    Application.HandleException(Self);
  end;
end;
 
procedure TForm2.FormActivate(Sender: TObject);
begin
  self.close;
end;



Un bug de Delphi :ouch:  
 
1/ Merci Lfi :hello:
 
Evidemment, ça peut toujours exister. Et c'est dur de tomber là-dessus, parce quelorsqu'on on programme et que l'on tombe sur un bug, la première chose à faire est de se remettre en question, et pas le compilateur :D  
 
Manifestement, Lfi est bel et bien un "vieux motard" et pas un amateur du dimanche :jap:
 
2/ J'ai résolu le problème par un CreateProcess() . Là, ça fonctionne nickel :sol: Le processus père appelle le processus fils. Dans un fichier temporaire, une structure contenant tous les paramètres dont le processus fils peut avoir besoin. C'est pas très élégant, je sais :spamafote: Mais sous DOS, quand je programmais en C, je faisais ça très souvent. Un programme se déployait sur plusieurs EXE, sans avoir besoin de passer par la technique des overlays (orthographe non garantie) trop fragile sous MSDOS.

Reply

Marsh Posté le 30-11-2007 à 11:34:40    

Cette année, j'ai eu le même problème dans un cas précis : quand je fais plusieurs showmodal pour un même objet fenêtre. Je ne sais pas si c'est du à notre VCL maison (utilisation d'une classe dérivé de TFORM) mais le ModalResult n'était pas remis automatiquement à zéro entre chaque appel et du coup dès le second appel, le bouton qui avait servit à fermer la fenêtre précédente ne permettait plus la fermeture automatique (le ModalResult ne changeant pas)
 
Ca peut être une piste si tu n'utilises pas le TForm classique.

Reply

Marsh Posté le 07-12-2007 à 21:33:07    

au fait, ne pas utiliser de nombre magique, les constantes c'est très utiles.
 
ModalResult := mrOK ou voir équivalent

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed