8
votes

Listbox tampon double

J'ai une commande checkedlistbox (WinForms) (qui hérite de la liste de liste; Googling montre que le problème est avec la liste de liste) qui est ancré aux quatre côtés de sa forme. Lorsque le formulaire est redimensionné, la boîte de liste a un scintillement laid. J'ai essayé de hériter de l'ordre checkedlistbox et de réglage DoubleBufferedd à TRUE dans le CTOR (cette technique fonctionne avec d'autres commandes, y compris ListView et DataGridView), mais elle n'avait aucun effet.

J'ai essayé d'ajouter le ws_ex_composited Style à Creatreparams , et cela a aidé, mais rend le formulaire redimensionner la musuleuse plus lentement.

Y a-t-il un autre moyen d'empêcher ce scintillement?


0 commentaires

4 Réponses :


2
votes

Vous pouvez vérifier si la commutation dans un contrôle ListView avec des cases à cocher améliore les choses. Ce n'est pas aussi facile à traiter (mais hé, la boîte de liste Winforms n'est pas un coup de génie non plus), j'ai constaté que cela redimensionne le comportement avec doublebuffered = true est supportable.

Alternativement, vous pouvez essayer de réduire le scintillement en remplaçant le dessin de fond des formes parent - permet de fournir une brosse creuse ou de remplacer wm_erasebknd en ne faisant rien et retourner vrai . (C'est bon si votre commande couvre l'ensemble de la zone client du formulaire parent, sinon vous auriez besoin d'une méthode de dessin de fond plus complexe.

J'ai utilisé cela avec succès dans les applications Win32, mais je ne sais pas si le contrôle des formulaires ajoute une partie de sa propre magie qui rend ce non fonctionnel.


0 commentaires

13
votes

J'avais des problèmes similaires, bien qu'un propriétaire tiré de la liste de liste. Ma solution consistait à utiliser des objets BufferedGraphics. Votre kilométrage peut varier avec cette solution si votre liste n'est pas tirée par le propriétaire, mais peut-être que cela vous inspirera.

J'ai constaté que Textrender a eu des difficultés au bon endroit, à moins que je ne puissiez pas de textformatflags.presvegraphicstranslatetransform. L'alternative à cela était d'utiliser p / invoke pour appeler BitBlt pour copier directement des pixels entre les contextes graphiques. J'ai choisi cela comme le moindre de deux maux. P> xxx pré>


le gdi code> classe (suggéré par françaistoast strong>) . P>

public static class GDI
{
    private const UInt32 SRCCOPY = 0x00CC0020;

    [DllImport("gdi32.dll", CallingConvention = CallingConvention.StdCall)]
    private static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, UInt32 dwRop);

    public static void CopyGraphics(Graphics g, Rectangle bounds, Graphics bufferedGraphics, Point p)
    {
        IntPtr hdc1 = g.GetHdc();
        IntPtr hdc2 = bufferedGraphics.GetHdc();

        BitBlt(hdc1, bounds.X, bounds.Y, 
            bounds.Width, bounds.Height, hdc2, p.X, p.Y, SRCCOPY);

        g.ReleaseHdc(hdc1);
        bufferedGraphics.ReleaseHdc(hdc2);
    }
}


11 commentaires

@ERIC: Où obtenez-vous GDI? Est-ce une référence? Par exemple, j'ai essayé d'ajouter graphiques gdi = this.creatiegraphics (); mais il n'a pas la méthode CopyGraphics. Ou avez-vous importé GDI32.DLL auparavant?


Ok - Travailler maintenant. J'ai ajouté gdi32.dll avec bitblt , enroulé comme gdi.copygraphics (...) et maintenant ça marche ... La seule chose est que cela scinde de la même manière que la liste d'origine. Des idées comment résoudre ce problème?


@Matt: La liste de liste est-elle définie pour être propriétaireDrawn?


@ERIC - faisez-vous référence à cet article de MSDN: Comment créer une liste de liste de propriétaireDeDrawawawaway ? Cela crée une liste dérivée de la classe Classe de la classe listbox , qui nécessite plus de code.


@Matt: Vous devez définir la propriété Drawstyle sur la liste de liste à OwnerDrawn.


@ERIC: Merci pour l'indice, OnDrawitem est appelé après que j'ai changé le drawmode. Je peux voir maintenant que j'ai un problème avec le bitBlt, car la fenêtre ListBox est entièrement vide - devra trier cela.


@Matt: la fenêtre est vide car avec une liste de liste OwnerDrawawawaway, vous devez dessiner le contenu (texte et / ou graphique) pour chaque élément de la liste de la liste en manipulant l'événement Drawitem.


@ Scientifique: j'ai ajouté privé vide listboxOutput_drawitem (expéditeur d'objet, drawitemeventargs e) {var lb = (ListBox) Sender; var item = lb.items [e.index] .tostring (); var pinceau = brosses.black; e.graphics.drawstring (article, lb.font, brosse, e.bounds); } qui fonctionne dans une liste normale avec DrawMode = OwnerDrawfixed , avec la doublebufferedlistbox, seule la barre de défilement verticale est mise à jour, la Textarea reste vide. Un point d'arrêt montre que le code est exécuté.


Eric, pourriez-vous s'il vous plaît poster le gdi.copygraphics méthode wrapper?


@Jeremythompson: Ce n'est pas complexe mais nécessite un peu de code. À son noyau, il s'agit d'une enveloppe autour de la méthode BitBlt GDI, qui utilise plusieurs structures et enums. Vous pouvez vérifier Pinvoke.net pour obtenir des détails sur la façon d'envelopper cela.


@Jeremythompson, j'ai googlé gdi.copygraphics, et je l'ai trouvé ici



0
votes

Ceci utilisé pour être géré en envoyant le message WM_SetReDraw au contrôle.

const int WM_SETREDRAW = 0x0b;

Message m = Message.Create(yourlistbox.Handle, WM_SETREDRAW, (IntPtr) 0, (IntPtr) 0);
yourform.DefWndProc(ref m);

// do your updating or whatever else causes the flicker

Message m = Message.Create(yourlistbox.Handle, WM_SETREDRAW, (IntPtr) 1, (IntPtr) 0);
yourform.DefWndProc(ref m);


3 commentaires

Le scintillement est causé par le redimensionnement, ce n'est donc pas une solution optimale. Cependant, je pourrais le faire quand même.


Cela ne résout pas le problème vacillant sur ma liste de liste.


Cette réponse est fausse car votre code n'est même pas exécuté lorsque le formulaire est redimensionné.



0
votes

Bien que de ne pas aborder la question spécifique de scintillement, une méthode fréquemment efficace pour ce type de problème est de mettre en cache un état minimal des éléments de liste de liste. Déterminez ensuite si vous devez redessiner la liste de liste en effectuant un calcul sur chaque élément. Seul la mise à jour de la liste de liste si au moins un élément doit être mis à jour (et bien sûr, enregistrez ce nouvel état dans le cache du cycle suivant).


0 commentaires