在c#中在控件上绘制图层的最佳方法是什么?

时间:2015-12-28 03:13:17

标签: c# graphics bitmap

简化一下,我有一个自定义控件,以每秒20帧的速度绘制LED条形声级计(收到数据时)。我当前的实现工作正常,但是屏幕上有16个控件,它在旧机器上消耗了太多的CPU ......我知道它可以更好。

目前我正在重写onDraw()以按顺序绘制以下图层:

  1. 不会更改的缓存背景位图
  2. 带有e.Graphics.DrawImageUnscaled()的可变位置的箭头
  3. e.Graphics.FillRectangle()根据数据填充绿色/黄色/红色
  4. e.Graphics.DrawString()在顶部绘制值
  5. 这是最终产品的模型:

    Bargraph Example

    这是最好的方法吗?我可以想象将所有内容预渲染成位图并根据需要剪切它们......并且可能仍然使用DrawString作为数字(?)......但最好的方法是什么?我应该在onDraw()中做到这一点吗? c#中的图形函数不是我最强的区域。

    感谢您提供任何建议。

    编辑:听起来我的表现和WinForms一样好,而且它实际上做得很好。在我的开发机器上,它只用了0.32ms来绘制控件。我对100%CPU使用率和丢帧率的投诉作出反应,但客户使用的是10年前的硬件,我怀疑图形适配器不是很好。

    尽管如此,这篇文章对于一般的改进非常有帮助,并且在绘画时间上缩短了几微秒:

    https://stackoverflow.com/a/11025428/1195740

2 个答案:

答案 0 :(得分:0)

假设您的项目是WPF代码。我认为每秒20次更新比一个人可以观看的更多,尤其是顶级数字更新。我认为一秒钟的更新就足够了,但我当然不知道你的应用程序的要求。

我掀起了一个示例,看看WPF UserControl可能会如何执行,并且在不使用图形类的情况下表现良好,只需从EllipseTextBox和{{1}构建控件}。滑块不难重新设计,我在样本中没有这样做。

设计模式

Design Mode

运行时

When Running

源代码

您可以在LightBar

在GitHub上找到我的项目

结论

如果这有帮助,那很好。您要求Slider以及这是否是最好的方法。不确定我的示例代码是否是最好的,而是可以解决任何此类问题的众多方法之一。

快乐的编码,Kory

答案 1 :(得分:0)

假设Winforms,这是一个相当快速且相当肮脏的例子。

它使用两个固定图像:

enter image description here enter image description here

  • 它不显示黄色三角形或数字。

  • 它甚至不会以持久的方式绘制图形。但对于这种情况,这可能是不必要的..!?

因此它留有一些改进空间。但它确实有效,而且非常简单:

public Form1()
{
    InitializeComponent();

    Bitmap level = (Bitmap)Image.FromFile("D:\\LEDmeter0.png");
    bmpL0 = level.Clone(new Rectangle(Point.Empty, level.Size), 
                        PixelFormat.Format32bppPArgb);
    level = (Bitmap)Image.FromFile("D:\\LEDmeter1.png");
    bmpL1 = level.Clone(new Rectangle(Point.Empty, level.Size), 
                        PixelFormat.Format32bppPArgb);
}

Bitmap bmpL0 = null;
Bitmap bmpL1 = null;


Random R = new Random(0);

private void timer1_Tick(object sender, EventArgs e)
{
    Size sz = pictureBox2.ClientSize;
    int level = R.Next(10) + R.Next(5) + R.Next(3) ;  // 0-17
    level = 27 * level + 50;
    using (Graphics G = pictureBox2.CreateGraphics())
    {
        G.DrawImage(bmpL1, new Rectangle(0, 0, sz.Width, sz.Height),
            new Rectangle(0, 0, sz.Width, sz.Height), GraphicsUnit.Pixel);
        G.DrawImage(bmpL0, new Rectangle(0, 0, sz.Width, level),
            new Rectangle(0, 0, sz.Width, level), GraphicsUnit.Pixel);
    }
}