Dans mon application, je passe constamment d'un contrôle à un autre. J'ai créé non. des commandes utilisateur, mais pendant la navigation, mes commandes scintillent. la mise à jour prend 1 ou 2 secondes. J'ai essayé de régler ça
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
or
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
mais cela n'a pas aidé ... Chaque contrôle a la même image de fond avec des contrôles différents. Alors, quelle est la solution pour cela ..
Merci.
c#
winforms
user-controls
flicker
Royson
la source
la source
UpdateStyles
après avoir défini ces paramètres? C'est mal documenté, mais peut parfois être nécessaire.Réponses:
Ce n'est pas le genre de scintillement que le double tampon peut résoudre. Ni BeginUpdate ou SuspendLayout. Vous avez trop de contrôles, BackgroundImage peut faire un beaucoup pire.
Il démarre lorsque UserControl se peint lui-même. Il dessine le BackgroundImage, laissant des trous là où vont les fenêtres de contrôle enfant. Chaque contrôle enfant reçoit alors un message pour se peindre, ils rempliront le trou avec le contenu de leur fenêtre. Lorsque vous disposez de nombreux contrôles, ces trous sont visibles par l'utilisateur pendant un certain temps. Ils sont normalement blancs, contrastant mal avec BackgroundImage lorsqu'il fait sombre. Ou ils peuvent être noirs si le formulaire a sa propriété Opacity ou TransparencyKey définie, ce qui contraste mal avec à peu près tout.
Il s'agit d'une limitation assez fondamentale de Windows Forms, elle est bloquée par la façon dont Windows rend les fenêtres. Corrigé par WPF btw, il n'utilise pas de fenêtres pour les contrôles enfants. Ce que vous souhaitez, c'est la double mise en tampon de l'ensemble du formulaire, y compris les contrôles enfants. C'est possible, vérifiez mon code dans ce fil pour la solution. Il a cependant des effets secondaires et n'augmente pas réellement la vitesse de peinture. Le code est simple, collez ceci dans votre formulaire (pas dans le contrôle utilisateur):
Il y a beaucoup de choses que vous pouvez faire pour améliorer la vitesse de peinture, au point que le scintillement n'est plus perceptible. Commencez par vous attaquer à BackgroundImage. Ils peuvent être très coûteux lorsque l'image source est volumineuse et doit être réduite pour s'adapter au contrôle. Modifiez la propriété BackgroundImageLayout sur "Tile". Si cela donne une accélération notable, revenez à votre programme de peinture et redimensionnez l'image pour qu'elle corresponde mieux à la taille de contrôle typique. Ou écrivez du code dans la méthode OnResize () de l'UC pour créer une copie correctement dimensionnée de l'image afin qu'elle n'ait pas à être redimensionnée à chaque fois que le contrôle est repeint. Utilisez le format de pixel Format32bppPArgb pour cette copie, il rend environ 10 fois plus rapide que tout autre format de pixel.
La prochaine chose que vous pouvez faire est d'éviter que les trous ne soient si visibles et contrastent mal avec l'image. Vous pouvez désactiver l'indicateur de style WS_CLIPCHILDREN pour l'UC, l'indicateur qui empêche l'UC de peindre dans la zone où se trouvent les contrôles enfants. Collez ce code dans le code de UserControl:
Les contrôles enfants vont maintenant se peindre au-dessus de l'image d'arrière-plan. Vous pourriez encore les voir se peindre un par un, mais le trou blanc ou noir intermédiaire laid ne sera pas visible.
Enfin, la réduction du nombre de contrôles enfants est toujours une bonne approche pour résoudre les problèmes de peinture lente. Remplacez l'événement OnPaint () de l'UC et dessinez ce qui est maintenant affiché dans un enfant. Les étiquettes et PictureBox particulières sont très inutiles. Pratique pour pointer et cliquer, mais leur alternative légère (dessiner une chaîne ou une image) ne prend qu'une seule ligne de code dans votre méthode OnPaint ().
la source
C'est un vrai problème, et la réponse que Hans Passant a donnée est excellente pour sauver le scintillement. Cependant, il y a des effets secondaires comme il l'a mentionné, et ils peuvent être laids (UI moche). Comme indiqué, "Vous pouvez désactiver l'
WS_CLIPCHILDREN
indicateur de style pour l'UC", mais cela ne le désactive que pour un UC. Les composants du formulaire principal présentent toujours des problèmes.Par exemple, une barre de défilement de panneau ne peint pas, car elle se trouve techniquement dans la zone enfant. Cependant, le composant enfant ne dessine pas la barre de défilement, il n'est donc pas peint tant que la souris n'est pas dessus (ou qu'un autre événement le déclenche).
De plus, les icônes animées (changer d'icônes dans une boucle d'attente) ne fonctionnent pas. La suppression des icônes sur un
tabPage.ImageKey
ne redimensionne / ne repeint pas les autres tabPages de manière appropriée.Je cherchais donc un moyen de désactiver la
WS_CLIPCHILDREN
peinture initiale pour que mon formulaire se charge bien peint, ou mieux encore ne l'activer que lors du redimensionnement de mon formulaire avec de nombreux composants.L'astuce consiste à faire appeler l'application
CreateParams
avec leWS_EX_COMPOSITED/WS_CLIPCHILDREN
style souhaité . J'ai trouvé un hack ici ( https://web.archive.org/web/20161026205944/http://www.angryhacker.com/blog/archive/2010/07/21/how-to-get-rid-of- flicker-on-windows-forms-applications.aspx ) et cela fonctionne très bien. Merci AngryHacker!Je mets l'
TurnOnFormLevelDoubleBuffering()
appel dans l'ResizeBegin
événement form etTurnOffFormLevelDoubleBuffering()
j'appelle le formulaire événement ResizeEnd (ou je le laisse simplementWS_CLIPCHILDREN
après avoir été initialement peint correctement.)la source
Si vous effectuez une peinture personnalisée dans le contrôle (c'est-à-dire en remplaçant OnPaint), vous pouvez essayer vous-même la double mise en mémoire tampon.
Et invalidez votre contrôle avec une propriété
NeedRepaint
Sinon, la réponse ci-dessus avec SuspendLayout et ResumeLayout est probablement ce que vous voulez.
la source
if (image != null) image.Dispose();
avantimage = new Bitmap...
Essayez les méthodes BeginUpdate / EndUpdate OU SuspendLayout / ResumeLayout. Voir ci-dessous
Comment résoudre les problèmes de scintillement des contrôles winform imbriqués Scintillement
lors des mises à jour des contrôles dans WinForms (par exemple DataGridView)
la source
Sur le formulaire principal ou le contrôle utilisateur où réside l'image d'arrière-plan, définissez la
BackgroundImageLayout
propriété surCenter
ouStretch
. Vous remarquerez une grande différence lors du rendu du contrôle utilisateur.la source
J'ai essayé d'ajouter ceci en commentaire mais je n'ai pas assez de points. C'est la seule chose qui a jamais aidé mes problèmes vacillants tant merci à Hans pour son message. Pour tous ceux qui utilisent le constructeur c ++ comme moi, voici la traduction
Ajoutez la déclaration CreateParams au fichier .h du formulaire principal de votre application, par exemple
et ajoutez ceci à votre fichier .cpp
la source
Mettez le code ci-dessous dans votre constructeur ou dans l'événement OnLoad et si vous utilisez une sorte de contrôle utilisateur personnalisé ayant des sous-contrôles, vous devrez vous assurer que ces contrôles personnalisés sont également en double tampon (même si dans la documentation MS, ils disent il est défini sur true par défaut).
Si vous créez un contrôle personnalisé, vous souhaiterez peut-être ajouter cet indicateur dans votre ctor:
Vous pouvez éventuellement utiliser ce code dans votre formulaire / contrôle:
Nous parcourons tous les contrôles du formulaire / contrôle et accédons à leur
DoubleBuffered
propriété, puis nous le changeons en true afin de rendre chaque contrôle du formulaire double tamponné. La raison pour laquelle nous réfléchissons ici, c'est parce qu'imaginez que vous avez un contrôle qui a des contrôles enfants qui ne sont pas accessibles, de cette façon, même s'il s'agit de contrôles privés, nous changerons toujours leur propriété en true.Vous trouverez plus d'informations sur la technique de double tamponnage ici .
Il y a une autre propriété que je remplace généralement pour trier ce problème:
WS_EX_COMPOSITED
- Peint tous les descendants d'une fenêtre dans l'ordre de peinture de bas en haut en utilisant la double mise en tampon.Vous pouvez trouver plus de ces drapeaux de style ici .
J'espère que cela pourra aider!
la source
Juste pour ajouter à la réponse de Hans:
(Version TLDR: la transparence est plus lourde que vous ne le pensez, utilisez uniquement des couleurs unies partout)
Si WS_EX_COMPOSITED, DoubleBuffered et WS_CLIPCHILDREN n'ont pas résolu votre scintillement (pour moi WS_CLIPCHILDREN l'a aggravé), essayez ceci: parcourez TOUS vos contrôles et tout votre code, et partout où vous avez Toute transparence ou semi-transparence pour BackColor, ForeColor, ou toute autre couleur, supprimez-la simplement, utilisez uniquement des couleurs unies. Dans la plupart des cas où vous pensez que vous ne devez utiliser la transparence, vous ne le faites pas. Reconcevez votre code et vos contrôles et utilisez des couleurs unies. J'avais un scintillement terrible et terrible et le programme fonctionnait lentement. Une fois que j'ai supprimé la transparence, elle s'est considérablement accélérée et il n'y a pas de scintillement.
EDIT: Pour ajouter plus, je viens de découvrir que WS_EX_COMPOSITED n'a pas besoin d'être à l'échelle de la fenêtre, il pourrait être appliqué uniquement à des contrôles spécifiques! Cela m'a évité beaucoup de problèmes. Créez simplement un contrôle personnalisé hérité de tout contrôle dont vous avez besoin et collez le remplacement déjà publié pour WS_EX_COMPOSITED. De cette façon, vous obtenez un double tampon de bas niveau sur ce contrôle uniquement, évitant ainsi les effets secondaires désagréables dans le reste de l'application!
la source
Je sais que cette question est très ancienne, mais je veux donner mon expérience à ce sujet.
J'ai eu beaucoup de problèmes avec le
Tabcontrol
scintillement dans un formulaire avec un dépassementOnPaint
et / ouOnPaintBackGround
sous Windows 8 en utilisant .NET 4.0.La seule pensée qui a fonctionné a été de NE PAS UTILISER la
Graphics.DrawImage
méthode dans lesOnPaint
substitutions, en d'autres termes, lorsque le dessin a été fait directement sur les graphiques fournis par lePaintEventArgs
, même en peignant tout le rectangle, le scintillement a disparu. Mais si appeler leDrawImage
méthode, même en dessinant un Bitmap découpé (créé pour une double mise en tampon), le scintillement apparaît.J'espère que ça aide!
la source
J'ai combiné ce correctif de scintillement et ce correctif de police , puis j'ai dû ajouter un peu de mon propre code pour démarrer un minuteur sur la peinture pour invalider le TabControl lorsqu'il passe hors écran et retour, etc.
Tous les trois font ceci:
Je ne suis pas le créateur mais d'après ce que j'ai compris, le bitmap évite tout le bogue.
C'était la seule chose qui résolvait définitivement le scintillement de TabControl (avec des icônes) pour moi.
vidéo de résultat de différence: vanilla tabcontrol vs tabcontrolex
http://gfycat.com/FineGlitteringDeermouse
ps. vous devrez définir HotTrack = true, car cela corrige également ce bogue
la source
Avez-vous essayé
Control.DoubleBuffered
Property?Aussi ceci et cela pourrait aider.
la source
Il n'y a pas besoin de double tampon et de tout ça les gars ...
Une solution simple ...
Si vous utilisez l'interface MDI, collez simplement le code ci-dessous dans le formulaire principal. Cela supprimera tout scintillement des pages. Cependant, certaines pages qui nécessitent plus de temps pour le chargement apparaîtront dans 1 ou 2 secondes. Mais c'est mieux que d'afficher une page scintillante dans laquelle chaque élément vient un par un.
C'est la seule meilleure solution pour toute l'application. Voir le code à mettre dans le formulaire principal:
la source