Primordial DrawItem pour la zone de liste - articles non sélectionnés ne sont pas redessiné

StackOverflow https://stackoverflow.com/questions/3274861

Question

C'est une application de bureau C#.L' DrawStyle propriété de mon ListBox est fixé à OwnerDrawFixed.

Le problème: Je remplace DrawItem pour dessiner du texte dans différentes polices de caractères, et il fonctionne.Mais quand je commence à redimensionner le formulaire au moment de l'exécution, l'élément sélectionné est établie correctement, mais le reste d'entre eux ne sont pas redessiné, causant de texte à la recherche corrompus pour les articles non sélectionnés.

Voici mon code:

private void listDevices_DrawItem(object sender, DrawItemEventArgs e)
{
    e.DrawBackground();

    string textDevice = ((ListBox)sender).Items[e.Index].ToString();

    e.Graphics.DrawString(textDevice,
        new Font("Ariel", 15, FontStyle.Bold), new SolidBrush(Color.Black), 
        e.Bounds, StringFormat.GenericDefault);


    // Figure out where to draw IP
    StringFormat copy = new StringFormat(
        StringFormatFlags.NoWrap |
        StringFormatFlags.MeasureTrailingSpaces
    );
    copy.SetMeasurableCharacterRanges(new CharacterRange[] {new CharacterRange(0, textDevice.Length)});

    Region[] regions = e.Graphics.MeasureCharacterRanges(
        textDevice, new Font("Ariel", 15, FontStyle.Bold), e.Bounds, copy);

    int width = (int)(regions[0].GetBounds(e.Graphics).Width);
    Rectangle rect = e.Bounds;
    rect.X += width;
    rect.Width -= width;

    // draw IP
    e.Graphics.DrawString(" 255.255.255.255",
        new Font("Courier New", 10), new SolidBrush(Color.DarkBlue),
        rect, copy);

    e.DrawFocusRectangle();
}

listDevices.Items.Add("Device001");
listDevices.Items.Add("Device002");

Aussi, l'élément qui est dessiné correctement (celui sélectionné) clignote sur le formulaire de redimensionnement.Pas trop grave, mais si quelqu'un sait pourquoi....tnx

Était-ce utile?

La solution

Placez le code suivant dans l'événement Resize:

private void listDevices_Resize(object sender, EventArgs e) {
    listDevices.Invalidate();
}

Cela devrait faire en sorte que tout soit redessiné.

Pour arrêter le clignotement, vous avez besoin de double mise en mémoire tampon.

Pour ce faire, une nouvelle classe, dérivé de la zone de liste, et placez le code suivant dans le constructeur:

this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

Ou tout simplement les coller dans un fichier de code:

using System.Windows.Forms;

namespace Whatever {
    public class DBListBox : ListBox {
        public DBListBox(): base() {
            this.DoubleBuffered = true;
            // OR
            // this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        }
    }
}

Remplacer "Quelque chose", avec l'espace de noms dans votre projet, ou faire quelque chose de plus utile.Après la compilation, vous devriez être en mesure d'ajouter un DBListBox dans le concepteur de formulaire.

Autres conseils

J'ai reproduit le problème.Il y a plusieurs erreurs dans le code, le nom de la police est "Arial", vous ne devriez pas régler rect.Largeur, vous oubliez d'appel dispose() sur les polices, les pinceaux et les régions.Mais ils n'ont pas d'expliquer le comportement.Il y a quelque chose de mal avec le découpage de la zone qui empêche le texte d'être correctement mis à jour.Je ne vois pas où cela se produit, l'objet Graphique de l'état est correct.

Les graphiques.Cordon de serrage() est une mauvaise méthode, vous devriez vraiment éviter.Tous les contrôles Windows Forms, y compris la zone de liste, utilisez TextRenderer.DrawText().Qui permet de résoudre le problème lorsque je l'utilise.Je sais que la mesure est plus difficile, vous pouvez contourner ce problème en affichant l'adresse IP fixe à un décalage.Regarde mieux, ils vont s'aligner dans une colonne de cette façon.

Il scintille, car vous utilisez l'e.DrawBackground().Qui efface le texte existant, vous dessinez le texte de droit de retour sur elle.Je ne pense pas que le double-buffering est à résoudre ce problème, vous devez dessiner l'ensemble de l'élément de sorte que vous n'avez pas à dessiner l'arrière-plan.Délicat si vous ne pouvez pas obtenir la taille exacte du texte avec la police de grande taille, une solution de contournement consiste à dessiner dans une image bitmap en premier.

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