L'activation de plusieurs fenêtres d'application ne fonctionne pas correctement

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

  •  03-07-2019
  •  | 
  •  

Question

J'ai une application Delphi dont le formulaire principal est un navigateur de documents. Lorsque l'utilisateur ouvre un document, nous ouvrons une fenêtre d'éditeur. Nous voulons que chaque éditeur possède un bouton dans la barre des tâches, ainsi que le formulaire principal. J'ai appliqué le code normal pour faire cela (ci-dessous), mais lorsque je clique sur le formulaire principal après avoir utilisé la fenêtre de l'éditeur, l'éditeur reste en haut, tandis que le focus est sur le formulaire principal. Je ne parviens pas à déterminer la cause de ce comportement.

Mise en scène: j'ouvre le formulaire principal et un formulaire de document.

  1. Cliquez sur une autre application, cliquez sur le formulaire principal, celui-ci reste ciblé. (Se comporter comme prévu.)

  2. Cliquez sur le formulaire de document, cliquez sur le formulaire principal, le formulaire de document vient dos à l'avant, mais montré inactif. (L'image montre le résultat)

texte alt http://www.matthew-jones.com/temp_xfer/titlebarfailure .jpg

La première étape, c'est Delphi 2007, et j'ai dans le projet:

Application.MainFormOnTaskBar := True;

Pour le formulaire principal, je n'ai pas de code supplémentaire.

Pour le formulaire de document, j'ai

procedure TCommonEditForm.CreateParams(var params: TCreateParams);
begin
  inherited;
  params.WndParent := 0; // GetDeskTopWindow; no diff
end;

J'ai essayé de déterminer s'il y avait un message qui fait que cela se produise, mais je ne trouve rien qui soit approprié. J'ai recherché dans le code tout ce qui a trait à & "Activer &" ;. Les indices sont les bienvenus!

Était-ce utile?

La solution

Mon application fonctionne comme vous le décrivez. Voici l'approche que j'ai prise. J'aurais aimé trouver une approche plus simple mais je ne l'ai jamais fait.

J'ai commencé par lire ces articles. Le premier est une excellente rédaction de Peter Below:

http: // groupes -beta.google.com/group/borland.public.delphi.winapi/msg/e9f75ff48ce960eb?hl=fr

D'autres informations ont également été trouvées ici, mais cela ne s'est pas avéré être une solution valable: pour mon utilisation:    http://blogs.teamb.com/DeepakShenoy/archive/ 2005/04/26 / 4050.aspx

Finalement, voici ce avec quoi j'ai fini.

Mon écran de démarrage sert également de formulaire principal d'application. Le formulaire principal a un lien particulier avec l'objet Application. Utiliser toutes les formes secondaires me procure le comportement que je recherchais.

Dans chaque formulaire que je veux dans la barre des tâches, je remplace CreateParams. Je le fais sur mes formulaires de modification et ce que les utilisateurs voient comme le & "Formulaire principal &";

procedure TUaarSalesMain.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
  Params.WndParent := GetDesktopWindow;
end;

Mon " Principal " formulaire en ce qui concerne Delphi charge le véritable formulaire principal dans sa fonction Activitate. J'utilise une variable membre pour garder une trace de la première activation. Puis, à la fin de la fonction, je masque le formulaire de démarrage, mais ne le ferme pas. Cela était important pour moi, car si l'utilisateur modifiait un document et fermait le formulaire principal, je ne voulais pas que les écrans d'édition soient forcés en même temps. De cette manière, toutes les formes visibles sont traitées de la même manière.

    if FFirstActivate = false then
      exit;

    FFristActivate := false;

    /* 
       Main Load code here 
       Update Splash label, repaint
       Application.CreateForm
       etc.
    */


    // I can't change visible here but I can change the size of the window
    Self.Height := 0;
    Self.Width := 0;
    Self.Enabled := false;

    //  It is tempting to set Self.Visible := false here but that is not
    // possible because you can't change the Visible status inside this
    // function.  So we need to send a message instead.
    ShowWindow(Self.Handle, SW_HIDE);

  end;

Mais il y a toujours un problème. Vous avez besoin de la fenêtre principale / de démarrage pour se fermer lorsque tous les autres formulaires sont fermés. J'ai un contrôle supplémentaire dans mes routines proches pour Parent & Lt; & Gt; nil parce que j'utilise des formulaires en tant que plugins (mes objectifs sont meilleurs que les cadres).

Je n'ai pas vraiment aimé utiliser l'événement Idle, mais je n'ai pas remarqué que cela ralentissait le processeur.

{
  TApplicationManager.ApplicationEventsIdle
  ---------------------------------------------------------------------------
}
procedure TApplicationManager.ApplicationEventsIdle(Sender: TObject;
  var Done: Boolean);
begin

  if Screen.FormCount < 2 then
    Close;
end;

{
  TApplicationManager.FormCloseQuery
  ---------------------------------------------------------------------------
}
procedure TApplicationManager.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
var
  i: integer;
begin

  for i := 0 to Screen.FormCount - 1 do
  begin
    if Screen.Forms[i] <> self then
    begin
      // Forms that have a parent will be cleaned up by that parent so
      // ignore them here and only attempt to close the parent forms
      if Screen.Forms[i].Parent = nil then
      begin
        if Screen.Forms[i].CloseQuery = false then
        begin
          CanClose := false;
          break;
        end;
      end;
    end;
  end;

end;

{
  TApplicationManager.FormClose
  ---------------------------------------------------------------------------
}
procedure TApplicationManager.FormClose(Sender: TObject;
  var Action: TCloseAction);
var
  i: integer;
begin

  for i := Screen.FormCount - 1 downto 0 do
  begin
    if Screen.Forms[i] <> self then
    begin
      // Forms that have a parent will be cleaned up by that parent so
      // ignore them here and only attempt to close the parent forms
      if Screen.Forms[i].Parent = nil then
      begin
        Screen.Forms[i].Close;
      end;
    end;
  end;

end;

Cela m’a bien servi jusqu’à présent. J'ai fait un petit changement pour Vista car l'icône de mon & "Main / Splash &"; l'écran était toujours visible. Je ne me souviens plus de ce que c'était. Je n'ai probablement pas besoin de définir largeur, hauteur, activé et d'envoyer le message masqué sur l'écran de démarrage. Je voulais juste m'assurer qu'il ne soit pas visible: -).

Il était nécessaire de gérer les événements proches. Si je me souviens bien, cela était nécessaire pour le moment où Windows envoyait un message d'arrêt. Je pense que seul le formulaire principal reçoit ce message.

Autres conseils

Désolé si c'est vraiment stupide, mais vous n'avez pas défini le style de style sur fsStayOnTop, n'est-ce pas? Cela expliquerait ce comportement.

peut-être ajouter ceci dans les createparams

Params.ExStyle := Params.ExStyle OR WS_EX_APPWINDOW;

ou essayez ceci n'importe où dans le code. Je l’utilise de manière presonale sur les formulaires .OnCreate event.

SetWindowLong(Wnd, GWL_EXSTYLE, 
  GetWindowLong(Wnd, GWL_EXSTYLE) or WS_EX_APPWINDOW) ;

l’inconvénient est que si le formulaire principal est minimisé, les autres formulaires se cachent également, mais sont restaurés lorsque le formulaire principal le fait.

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