Animation & # 8220; lueur & # 8221; dans la barre de progression dessinée par le propriétaire (ListView / DataGridView)

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

Question

J'ai remarqué que ProgressBar, standard standard dans .NET 2.0 (Winforms), apparaît comme la barre animée animée de fantaisie de Vista. Cependant, l'utilisation de ProgressBarRenderer (comme c'est généralement le cas lorsque vous essayez de dessiner une barre de progression dans une vue liste, une vue grille ou tout autre contrôle de ce type) donne simplement le style visuel sans la jolie animation.

J'imagine qu'il était stupide de s'attendre à ce que cela fonctionne comme par magie. J'imagine que le contrôle natif de Vista doit comporter une sorte de minuteur intégré ou de fil qui, de toute évidence, n'existe pas lors du dessin d'une image statique. J'ai constaté que si vous redessiniez plusieurs fois de suite un contrôle ProgressBar (à l'aide de DrawToBitmap), vous pouvez voir les différentes étapes de la lueur animée. J'ai donc essayé d'utiliser une minuterie pour continuer à redessiner automatiquement, mais quelque chose ne va pas. le look, et il consomme également beaucoup plus de temps CPU qu'un ProgressBar réelle.

Cela semble me laisser avec deux options inférieures à la norme: a) Utilisez ProgressBarRenderer et obtenez Vista " look " mais pas d'animation; ou b) Utilisez un minuteur pour redessiner en continu plusieurs ProgressBars en bitmaps et gaspillez les cycles de l’UC pour qu’il ait une meilleure apparence, sans être pour autant parfait.

Je me demandais si quelqu'un avait déjà intégré des barres de progression dans des contrôles définis par le propriétaire et connaissait un meilleur moyen que les deux options ci-dessus - quelque chose qui puisse reproduire avec précision l'éclat / lueur sans avoir recours à des minuteries et / ou à la frappe CPU.

Était-ce utile?

La solution

J'ai dû faire quelques cascades assez folles pour que cela fonctionne. Malheureusement, MSFT n'a pas mis à jour la classe VisualStyleElement.ProgressBar pour ajouter les pièces ajoutées par Vista. Et le constructeur est privé. Et j'ai dû deviner un peu les parties qui produisent l'animation. Je suis assez proche de ce code, il devrait vous donner quelque chose à expérimenter:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using System.Reflection;

namespace WindowsFormsApplication1 {
  public partial class Form1 : Form {
    VisualStyleElement pulseOverlay;
    VisualStyleElement moveOverlay;
    VisualStyleRenderer pulseRenderer;
    VisualStyleRenderer moveRenderer;
    Timer animator = new Timer();
    public Form1() {
      InitializeComponent();
      ConstructorInfo ci = typeof(VisualStyleElement).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance,
        null, new Type[] { typeof(string), typeof(int), typeof(int) }, null);
      pulseOverlay = (VisualStyleElement)ci.Invoke(new object[] { "PROGRESS", 7, 0 });
      moveOverlay = (VisualStyleElement)ci.Invoke(new object[] { "PROGRESS", 8, 0 });
      pulseRenderer = new VisualStyleRenderer(pulseOverlay);
      moveRenderer = new VisualStyleRenderer(moveOverlay);
      animator.Interval = 20;
      animator.Tick += new EventHandler(animator_Tick);
      animator.Enabled = true;
      this.DoubleBuffered = true;
    }
    void animator_Tick(object sender, EventArgs e) {
      Invalidate();
    }

    int xpos;
    protected override void OnPaint(PaintEventArgs e) {
      Rectangle rc = new Rectangle(10, 10, 100, 20);
      ProgressBarRenderer.DrawHorizontalBar(e.Graphics, rc);
      rc = new Rectangle(10, 10, 50, 20);
      ProgressBarRenderer.DrawHorizontalChunks(e.Graphics, rc);
      xpos += 3;
      if (xpos >= 30) xpos = -150;  // Note: intentionally too far left
      rc = new Rectangle(xpos, 10, 50, 20);
      pulseRenderer.DrawBackground(e.Graphics, rc);
      moveRenderer.DrawBackground(e.Graphics, rc);
    }
  }

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