当前位置:  开发笔记 > 编程语言 > 正文

所有者绘制的进度栏中的动画“发光”(ListView / DataGridView)

如何解决《所有者绘制的进度栏中的动画“发光”(ListView/DataGridView)》经验,为你挑选了1个好方法。

我注意到,.NET 2.0(Winforms)中的沼泽标准ProgressBar确实在Vista中显示为花哨的动画发光条。但是,使用ProgressBarRenderer(通常尝试在所有者绘制的列表视图,网格视图或其他此类控件中绘制进度条时必须这样做)只能提供视觉效果,而没有漂亮的动画。

我想期望这会神奇地起作用是很愚蠢的-我想象Vista中的本机控件必须具有某种嵌入式计时器或线程,这些计时器或线程在绘制静态图像时显然不存在。我确实看到,如果您连续多次重画ProgressBar控件(使用DrawToBitmap),您实际上可以看到动画发光的不同阶段,所以我尝试使用计时器来保持自动重画,但是有些不对劲外观,并且比实际的ProgressBar占用更多的CPU时间。

这似乎给了我两个不合标准的选项:a)使用ProgressBarRenderer并以Vista“外观”结束但没有动画;或b)使用计时器连续将多个ProgressBar重新绘制到位图,并浪费CPU周期以使其看起来更好,但仍不完美。

我想知道是否有人体验过将进度条嵌入所有者绘制的控件中,并且可能知道比上述两个选项更好的方法-一种可以在不依赖计时器和/或重击CPU的情况下准确再现辉光/闪光的方法。



1> Hans Passant..:

为了完成这项工作,我不得不拉一些非常疯狂的特技。不幸的是,MSFT并未更新VisualStyleElement.ProgressBar类来添加Vista添加的部件。构造函数是私有的。我不得不猜测制作动画的部分。我与这段代码相当接近,它应该给你一些试验的方法:

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);
    }
  }

}


这对我来说非常有用,但是不需要使用反射来创建新的VisualStyleElements。您可以为此使用静态VisualStyleElement.CreateElement函数。
推荐阅读
贾志军
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有