2010-07-13 7 views
1

J'ai une application avec un TPageControl sur le formulaire principal. Le pagecontrol a plusieurs onglets. L'application peut être réduite à une icône de plateau. Parfois, après une exécution réduite pendant un moment, lorsque je restaure la fenêtre principale (en cliquant avec le bouton droit de la souris sur l'icône de la barre d'état), l'onglet affiché en dernier s'affiche, mais je ne peux pas sélectionner d'autres onglets! Si je clique sur un autre onglet, l'apparence change pour que l'onglet apparaisse actif (c'est-à-dire que l'onglet lui-même se place au début de la rangée d'onglets), mais le corps de l'onglet reste tel qu'il était . J'ai aussi des éléments de menu et des touches de raccourci pour sélectionner les autres onglets et ils se comportent de la même manière. Si je tape Alt-O (options) l'onglet d'options en haut devient actif mais je ne peux pas voir ce qui est sur le corps de cet onglet - je vois toujours le contenu de l'autre onglet.Delphi TPageControl ne répond pas aux clics sur les onglets

J'ai vérifié que la mise au point se déplace sur le premier onglet lorsque je clique sur un autre onglet et recule lorsque je clique sur cet onglet.

Je n'ai pas encore établi si le comportement est limité à un onglet particulier car il faut un certain temps pour qu'il se produise.

Des idées?

Mise à jour

Remarque intéressante. J'ai établi que le problème se produit dans ces circonstances. L'application est démarrée, puis réduite au niveau du bac. Une condition d'alerte est détectée, ouvre une fenêtre et restaure la fenêtre principale (comportement prévu de l'application). C'est à ce moment que la faute est observée, c'est-à-dire que je ne peux pas voir les autres onglets lorsque je clique dessus.

  • Démarrer l'application. L'onglet 1 est affiché
  • Réduire l'application. au plateau
  • Attendez pop-up pour montrer, la forme principale est restaurée
  • Cliquez sur l'onglet 2 DÉFAUT OBSERVE (Tab 2 corps n'affiche pas)
  • Put point d'arrêt dans TWinControl.CreateHandle
  • Cliquez sur l'onglet 3 - pauses
  • Run - ne montre pas l'onglet 3 corps
  • Cliquez sur l'onglet 1 - ne casse pas
  • Cliquez sur l'onglet 3 - ne rompt pas
  • Cliquez sur l'onglet 4 - pauses
  • Run - ne montre pas Tab 4 corps
  • Cliquez sur l'onglet 1, 2, 3, 4 - ne rompt pas

Il semble que les onglets créent leurs poignées la première fois qu'ils sont cliqué sur le bouton, et à partir de là ils pensent qu'ils existent, mais ils ne le montrent pas. Si la fenêtre contextuelle est désactivée, l'erreur n'est pas observée. La popup est déclenchée à partir d'une tâche Application.OnIdle.

Autre mise à jour: quelques progrès. Après avoir farfouillé sur le web, j'ai fait quelques changements.

J'ai supprimé le code suivant:

procedure RestoreMainWindow ; 

begin 
MainForm.WindowState := wsNormal ; 
MainForm.visible := true ; 
Application.Restore ; 
Application.BringToFront ; 
ShowWindow (Application.Handle, SW_SHOW) ; { show the taskbar button } 
end ; 

et remplacé avec:

procedure RestoreMainWindow ; 

begin 
MainForm.Show() ; 
MainForm.WindowState := wsNormal ; 
Application.BringToFront() ; 
ShowWindow (Application.Handle, SW_SHOW) ; { show the taskbar button } 
end ; 

Je retiré:

procedure TTADMainForm.SendToTray (Sender: TObject) ; 

begin 
MainForm.visible := false ; 
ShowWindow (Application.Handle, SW_HIDE) ; { hide the taskbar button } 
end ; 
... 
Application.OnMinimize := SendToTray ;  

et remplacé avec:

procedure TTADMainForm.ApplicationEvents1Minimize(Sender: TObject) ; 

begin 
Hide(); 
WindowState := wsMinimized ; 
TrayIcon1.Visible := True; 
end ; 

et le problème semble avoir disparu. TOUTEFOIS. Maintenant, je peux minimiser l'application après le démarrage, la popup se produit et montre modalement, le formulaire principal montre, tous les onglets affichent et fonctionnent. MAIS. Je ne peux pas minimiser le formulaire à nouveau. Le gestionnaire OnMinimize n'est pas déclenché après la première fois. Grrrrr.

Je n'arrive toujours pas à comprendre pourquoi cela fonctionne maintenant, ce qui est un peu inquiétant. Et comment puis-je l'obtenir pour minimiser encore ??

+0

Juste au cas où cela aide quelle version de Delphi? –

+0

Delphi 2006 est la version – rossmcm

Répondre

3

travail entièrement de mémoire il y a 5 ans, mais voilà:

TPageControl utilise une poignée de fenêtre différente pour chaque page en son sein. La barre d'onglets est son propre handle de fenêtre, et le TPageControl est responsable de l'écoute des changements d'onglet et de la création de masquer/afficher les pages correspondantes. Ainsi, lorsque vous cliquez sur un onglet et que l'onglet saute vers l'avant du pack, TPageControl est censé masquer la fenêtre de la page en cours et afficher la fenêtre de la page correspondant à l'onglet sélectionné.

Normalement, les contrôles VCL ne créent pas leur handle de fenêtre tant qu'il n'est pas réellement nécessaire - lorsqu'il est réellement affiché, par exemple. Cela réduit la consommation de la poignée de fenêtre. Critique important dans Windows 3.1 et Win95, mais pas si critique dans les systèmes d'exploitation 32 bits basés sur NT d'aujourd'hui.

Pour réduire la charge de ressources et le temps de démarrage, TPageControl ne crée pas de handles de fenêtre pour toutes ses pages masquées lorsque le contrôle est créé. Les poignées de la fenêtre de page seront créées lors de leur première apparition.

Il y a quelques possibilités pour lesquelles la page n'est pas tirée lorsque l'onglet est cliqué:

  1. aspirationNous la piscine de la poignée de fenêtre GDI. Extrêmement peu probable, sauf si vous utilisez un système d'exploitation Windows 16 bits. (Win 3.1 ou Win95)
  2. Fuite de mémoire entraînant le débordement de votre application dans le fichier d'échange et le débordement du disque dur. L'application va s'arrêter et sembler figée, avec des rotations de l'activité de l'interface utilisateur de temps en temps.
  3. Les poignées de fenêtre sont créées sur un thread d'arrière-plan qui n'a pas de boucle de message. Faites-vous quelque chose dans les discussions de fond? Si vous touchez un contrôle VCL dans un thread d'arrière-plan, le handle de fenêtre peut être créé prématurément et le handle de fenêtre sera lié au thread sur lequel il a été créé. Si ce thread n'a pas de boucle de message, alors ce handle de fenêtre ne recevra jamais de messages, donc il ne se dessinera jamais à l'écran.

Le numéro 3 est votre coupable le plus probable. Alors, que faites-vous dans ce fil de fond? ;>

+0

Merci pour la réponse détaillée. Il n'y a pas de raclage évident et après que l'événement s'est produit, l'application se comporte exactement comme je l'aurais espéré en ce qui concerne les contrôles que je peux voir.Il y a un fil de fond - mais je ne crois pas qu'il touche la VCL. Souhaitez-vous que toutes les pages du contrôle (il y en a 7) ne répondent plus? Si les poignées de Windows dans un scénario de thread d'arrière-plan est le cuplrit, une solution de secours serait de sélectionner par programme chaque page à son tour au démarrage? – rossmcm

+0

Vous devrez vérifier les docs ou le code source VCL pour TPageControl pour voir s'il détruit les poignées de la fenêtre de page lorsqu'il cache les pages. Je ne me souviens pas si c'est le cas ou non. Probablement fait dans les Win3.1 jours, mais n'est plus nécessaire dans Win32. – dthorpe

+2

S'il ne détruit pas le handle de fenêtre lorsqu'une page est cachée, alors oui, toucher toutes les poignées de la page au démarrage forcerait toutes les poignées à être créées. Cependant, faites attention ici parce que si vous avez une douzaine de pages à onglets et que chaque page a 20 contrôles, la création de toutes ces poignées prendra un peu de temps. C'est pourquoi nous avons changé TPageControl pour être paresseux - la boîte de dialogue d'options de l'EDI Delphi prenait trop de temps à charger! ;> – dthorpe

Questions connexes