2009-04-29 11 views
3

J'ai une application Delphi qui a un navigateur de document comme formulaire principal. Lorsque l'utilisateur ouvre un document, nous ouvrons une fenêtre d'éditeur. Nous voulons avoir chaque éditeur avec un bouton sur la barre des tâches, ainsi que le formulaire principal. J'ai appliqué le code normal pour le faire (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, alors que l'accent est mis sur le formulaire principal. Je suis incapable de déterminer ce qui cause ce comportement.L'activation de plusieurs fenêtres d'application ne fonctionne pas correctement

Réglage de l'étape: J'ouvre le formulaire principal et un formulaire de document.

  1. Cliquez sur une autre application, cliquez sur le formulaire principal, la forme principale reste concentrée. (comme prévu Behaving.)

  2. Cliquez sur le formulaire de document, cliquez sur le formulaire principal, sous forme de document vient arrière vers l'avant, mais montré inactif. (Photo montre résultat)

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

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

Application.MainFormOnTaskBar := True; 

Pour la principale forme, je n'ai pas de code supplémentaire.

Pour la forme de documents, j'ai

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

J'ai essayé de travailler s'il y a un message qui fait cela se produise, mais ne peut pas trouver quoi que ce soit approprié. J'ai cherché le code pour quelque chose à faire avec "activer". Des indices bienvenus!

Répondre

6

Mon application fonctionne de la manière que vous 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. Cette première est une grande écriture par Peter Ci-dessous:

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

Autres informations a également été trouvé ici, mais cela ne prouve pas être une solution valable: pour mon utilisation: http://blogs.teamb.com/DeepakShenoy/archive/2005/04/26/4050.aspx

Finalement, voici ce que j'ai fini avec.

Mon écran de démarrage sert également de formulaire principal d'application. Le formulaire principal a un lien spécial avec l'objet Application.Utiliser toutes les formes secondaires m'apporte le comportement que je cherchais.

Dans chaque formulaire que je veux dans la barre des tâches je substitue CreateParams. Je le fais sur mes formes d'édition et ce que les utilisateurs considère comme la « forme principale »

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

Ma forme « Main » dans la mesure où Delphi est la forme des charges concernées vraie principale dans sa fonction Activitate. J'utilise une variable membre pour suivre la première activation. Puis, à la fin de la fonction, je masque la forme splash, mais ne la ferme pas. C'était important pour moi car si l'utilisateur éditait un document et fermait le formulaire principal, je ne voulais pas que les écrans d'édition soient forcés de fermer en même temps. De cette façon, 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 devez fermer la fenêtre principale/splash lorsque tous les autres formulaires sont fermés. J'ai une vérification supplémentaire dans mes routines de fermeture pour Parent <> nil parce que j'utilise des formes comme plugins (forme mes objectifs ils fonctionnent mieux que les cadres).

Je n'aimais pas vraiment utiliser l'événement Idle, mais je ne remarque pas que ce soit un frein sur 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'ici. J'ai fait un petit changement pour Vista parce que l'icône de mon écran "Main/Splash" était toujours visible. Je ne me souviens pas de ce que c'était. Je n'ai probablement pas besoin de définir la largeur, la hauteur, activé et envoyer le message masquer sur l'écran de démarrage. Je voulais juste m'assurer que ça ne se voit pas :-).

La gestion des événements de proximité était nécessaire. Si je me souviens bien, c'était nécessaire quand Windows a envoyé un message d'arrêt. Je pense que seule la forme principale reçoit ce message.

+0

Le splash caché semble horrible, mais il pourrait aussi résoudre un autre problème. Cela pourrait être ce que je vais avec si rien d'idéal n'apparaît. Merci! – mj2008

+0

J'ai également adopté une approche similaire avec l'une de mes applications et cela a bien fonctionné. J'ai ajouté un peu de code pour appeler l'application de minimiser quand le "formulaire principal" a été réduit, et ajouté un événement à l'application.onrestore pour restaurer le "formulaire principal". – skamradt

+0

Je suis d'accord le splash caché est horrible. Si quelque chose de mieux apparaît, je vais aussi changer mon code :-). C'est dommage que stackoverflow n'était pas là quand j'ai écrit ça pour la première fois. –

0

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

+0

Non, c'est une bonne idée. FormStyle est fsNormal. PopupMode est pmNone. BorderStyle est bsSizeable. BorderIcons par défaut. – mj2008

0

peut-être ajouter ceci dans les CreateParams

Params.ExStyle := Params.ExStyle OR WS_EX_APPWINDOW; 

ou essayez ce soit dans le code. Je l'utilise par presonally sur les formes .OnCreate event.

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

l'inconvénient est que si la principale forme est réduite au minimum les autres formes cachent aswell, mais quand restaurer la forme principale fait.

+0

Merci - cela a été essayé aussi, mais à aucun effet (eh bien, pas à ce problème). (J'aurais dû le mentionner, mais je travaille dessus depuis un jour ou deux, et j'ai supprimé cette ligne qui a été commentée.) – mj2008

Questions connexes