Question

D'accord, donc dans ma demande, il y a un tas de WinAPI et quelques contrôles personnalisés. Yay ...

Maintenant, normalement, ils vont tout simplement se redessiner tranquillement pour les animations, changement d'état, ect .... et tout cela fonctionne très bien.

Mais j'ai une méthode de fenêtre de classe appelée fix (). Ceci est appelé à chaque fois que l'ensemble des besoins de fenêtre pour être mis à jour. Il redimensionne les commandes et Invalide la fenêtre.

Lorsque cela se produit, l'arrière-plan est établi, le contrôle onglet, puis tous les autres sur le dessus. Cela provoque très irritant clignote, en particulier lors du redimensionnement de la fenêtre (en raison des appels constants à fixer ()).

Ce que j'ai essayé:

  • WS_EX_COMPOSITED. Cela ne double tamponne les contrôles individuels. Son une amélioration, mais le reste vacillante inévitablement.
  • Mise hors dessin d'arrière-plan. permet de résoudre le problème à peine, et fait réellement empirer les choses.

: J'ai besoin d'une technique / méthode / whatever pour me permettre de doubler tampon la fenêtre dans son intégralité. Je me suis dit que la manipulation du message WM_PAINT par moi-même peut-être une solution, mais je ne sais pas où commencer. J'ai un sentiment horrible ce n'est pas même possible ...

S'il vous plaît aide, ceci est une question cruciale. Je serai très soulagé quand ce petit problème stupide est fixe.

Était-ce utile?

La solution

Il est à ce moment que l'on a réalisé les profondeurs de mépris Microsofts pour les développeurs natifs. On pourrait en effet commencer à héberger délires paranoïaques que Microsoft a délibérément cassé la peinture native afin de forcer les développeurs natifs de passer à WPF.

Tout d'abord, pensez à WS_EX_COMPOSITED. WS_EX_COMPOSITED semble être la moutarde: - il dit qu'il applique une botton en haut de l'ordre de peinture pour les contrôles enfants, et essentiellement que les messages WM_PAINT se traités dans un lot. Il dit qu'il a été ajouté dans Windows 2000 (5.0) et, quelques lignes plus bas, qu'il ne fonctionne pas avec la composition du bureau est activée. à-dire qu'il cesse de fonctionner comme de Windows Vista (6.0), à moins que le verre aéro est éteint et qui va le faire?

Ensuite, il y a deux possibles « hacks » pour essayer d'obtenir sans scintillement peinture au travail:

  • Tout d'abord, vous devez mimimize la quantité de surpeint. WS_EX_CLIPCHILDREN | WS_EX_CLIPSIBLINGS sont nécessaires pour faire en sorte que toute zone particulière de la fenêtre ne peint qu'une seule fois. BeginDeferWindowPos est également nécessaire pour les opérations de redimensionnement par lots jusqu'à faire en sorte que les états transitoires - où une fenêtre chevauche une autre -. ne se produit pas (à savoir lorsque la fenêtre A a été redimensionnée, mais la fenêtre B n'a pas)

Bien sûr, quand vous essayez de dessiner un dialogue peau, ou utiliser des boîtes de groupe, ou des contrôles de l'onglet, ou un certain nombre d'autres restrictions, WS_EX_CLIPSIBLINGS est tout simplement pas approprié.

  • WM_SETREDRAW est un message magique. Il n'y a pas d'API pour accéder à cette fonctionnalité: WM_SETREDRAW est gérée directement par DefWindowProc pour marquer essentiellement la fenêtre cachée pendant toute la durée. Après WM_SETREDRAW, FALSE est envoyé, les appels à GetDC / GetDCEx / etc GetWindowDC en utilisant la poignée de fenêtre parent (et tous ses enfants) retourne un DC qui ne sera pas dessiner sur l'écran. Cela vous donne une chance de faire toutes sortes de choses aux fenêtres de l'enfant, lorsque vous avez terminé envoyer un WM_SETREDRAW,TRUE, (puis repeindre la fenêtre manuellement). Toutes les fenêtres enfant - bien sûr -. Peinture dans leur propre temps, et après la fenêtre parent a fait son arrière-plan d'effacement, de sorte WM_SETREDRAW est aucune espèce de panacée

Après la rupture WS_EX_COMPOSITED, WinForms est dans .NET et WPF récrit les commandes à partir du sol pour ne pas utiliser les contrôles natifs, afin qu'ils puissent cuire là-dedans la peinture tampon. Et alpha soutien aussi.

Autres conseils

Hm. Avant que les gens se précipitent et près ce sujet comme doublon, je ferais mieux de mentionner que votre problème n'est pas double buffering en soi, mais vacillante lors du repositionnement des commandes, pour lesquelles la double mise en mémoire tampon « manuel » est seulement l'une des nombreuses solutions.

Il est peut-être que par exemple BeginDeferWindowPos et amis peuvent fixer le vacillement.

Disclaimer: J'ai connu presque tous les détails de l'API Win16, mais il a été quelques années depuis que je faisais la programmation au niveau de l'API

.

Vive et HTH.

- Alf

Sans code, j'imagine à peine quelle est la situation réelle ... Mais vous pouvez essayer de gérer WM_ERASEBKGND, retourner TRUE chaque fois que vous les avez reçus pour sauter l'effacement.

Poignée WM_ERASEBKGND pour votre fenêtre et dans la mise en œuvre exclut les rects de chacun de vos contrôles enfants, puis remplir convenablement l'arrière-plan restant et dire le cadre que vous avez peint l'arrière-plan urself en retournant true. Faites la même chose pour tous les autres contrôles enfants qui à leur tour détiennent d'autres contrôles tels que le contrôle onglet dans votre cas.

Voir un exemple en utilisant MFC.

Dans .net il y a ControlStyle.AllPaintingInWmPaint Cela devrait être placé sur chaque fenêtre de conteneur (donc la fenêtre principale et les onglets). Je ne pouvais pas trouver un équivalent winapi. Mais ce que cela fait est de déplacer la peinture de l'arrière-plan de WM_ERASEBKGND à WM_PAINT. il retranche aussi la zone de contrôle des enfants du parent pour éviter le scintillement, il pourrait être que vous devez le faire manuellement.

Je suis surpris WS_EX_COMPOSITED ne l'aide. Cela devrait fonctionner, si vous définissez que sur la fenêtre de niveau supérieur, et ne pas appeler RedrawWindow sur les commandes de sous.

Assurez-vous également à tester avec et sans DWM / Aero. Vous pouvez obtenir des résultats différents.

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