简体   繁体   English

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

[英]What is the best way to draw layers on a control in c#?

Simplifying a bit, I have a custom control that draws an LED bargraph sound level meter at 20 frames per second (as data is received). 简化一点,我有一个自定义控件,它以每秒20帧的速度绘制LED条形图声级计(接收到数据)。 My current implementation works okay, but with 16 controls on the screen it consumes too much CPU on older machines... I know it can be better. 我当前的实现还可以,但是屏幕上有16个控件,这会在旧计算机上消耗过多的CPU ...我知道这样会更好。

Currently I'm overriding onDraw() to draw the following layers in order: 当前,我重写onDraw()以按顺序绘制以下图层:

  1. A cached background bitmap that doesn't change 缓存的背景位图不变
  2. An arrow in a variable position with e.Graphics.DrawImageUnscaled() 使用e.Graphics.DrawImageUnscaled()在可变位置的箭头
  3. e.Graphics.FillRectangle() to fill Green/Yellow/Red based on data e.Graphics.FillRectangle()根据数据填充绿色/黄色/红色
  4. e.Graphics.DrawString() to draw value at the top e.Graphics.DrawString()在顶部绘制值

Here's a mockup of the final product: 这是最终产品的模型:

条形图示例

Is this the best way to do that? 这是最好的方法吗? I could conceivably pre-render everything into bitmaps and simply clip them as needed... and maybe still use DrawString for the number(?)... but what is the best approach? 我可以想像地将所有内容预先渲染到位图中,然后根据需要进行裁剪...并且可能仍然使用DrawString作为number(?)...,但是最好的方法是什么? Should I even be doing that in onDraw()? 我什至应该在onDraw()中这样做吗? Graphics functions in c# are not my strongest area. C#中的图形功能不是我最擅长的领域。

Thank you for any advice you can provide. 感谢您提供的任何建议。

Edit: Sounds like I'm doing about as good as WinForms will do and it's actually doing just fine. 编辑:听起来好像我做的和WinForms一样好,而且实际上做得很好。 On my development machine it's taking just 0.32ms to paint the control. 在我的开发机器上,仅需0.32毫秒即可绘制控件。 I'm reacting to a complaint of 100% CPU usage and dropped frames, but the customer is using 10-year-old hardware and I suspect the graphics adapter is not great. 我对CPU使用率达到100%和帧丢失的投诉做出了反应,但是客户使用的是10年以前的硬件,我怀疑图形适配器不是很好。

Still, this post was very helpful for general improvements, and did shave a few microseconds off my painting time: 尽管如此,这篇文章对于总体改进还是很有帮助的,并且确实节省了我的绘画时间几​​微秒:

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

Assuming your project is WPF code. 假设您的项目是WPF代码。 I would think 20 updates per second is more than a person could watch, especially with the top number updating. 我认为每秒20次更新比一个人可以观看的更多,尤其是在更新次数最多的情况下。 I would think a few updates a second would suffice, but I do not know the requirements of your app of course. 我认为每秒进行几次更新就足够了,但是我当然不知道您的应用程序的要求。

I whipped up a sample to see how a WPF UserControl might perform, and the perf seemed fine without using graphics classes, and just building the control from Ellipse , TextBox , and Slider . 我整理了一个示例,以查看WPF UserControl的性能如何,并且在不使用图形类的情况下,perf看起来还不错,而仅从EllipseTextBoxSlider构建TextBox The slider is not hard to re-style, and I did not do that in my sample. 重新设置滑块的样式并不难,我在示例中也没有这样做。

Design Mode 设计模式

设计模式

When Running 跑步时

跑步时

Source Code 源代码

You can find my project on GitHub at LightBar 您可以在LightBar的 GitHub上找到我的项目

Conclusion 结论

If this helps, great. 如果有帮助,那就太好了。 You asked for Advice and if this was the best way. 您要求Advice ,这是否是最好的方法。 Not sure if my sample code is the best, but rather one of the many ways any such problem could be solved. 不知道我的示例代码是否是最好的,而是解决此类问题的众多方法之一。

Happy coding, Kory 快乐编码,Kory

Assuming Winforms, this is a rather quick and pretty dirty example. 假设使用Winforms,这是一个非常快速且相当肮脏的示例。

It uses two fixed images: 它使用两个固定的图像:

在此处输入图片说明 在此处输入图片说明

  • It does not display the yellow triangle nor the number. 它不显示黄色三角形或数字。

  • And it doesn't even draw the graphics in a persistent way. 而且它甚至不能持久地绘制图形。 But this may be unnecessary anyway for this situation..!? 但是对于这种情况,这可能是不必要的。

So it leaves some room for improvement. 因此,它还有一些改进的余地。 But it does work and it extremly simple: 但这确实有效,而且极其简单:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C# 绘图:绘制中间有孔的多边形的最佳方法是什么 - C# Drawing: What is the best way to draw a polygon with a hole in the middle 在C#.NET中绘制实时频谱的最佳方法是什么? - What is the best way to draw realtime spectrum in C# .NET? 有没有办法在C#中对其他控件进行控制? - Is there any way to draw a control on some other control in C#? 用C ++编写控件以便可以被C ++和C#程序使用的最佳方法是什么? - What is the best way to write a control in C++ so that it can be used by C++ and C# programs? 在C#中以流畅的方式绘制运动球体的最佳方法 - Best way to draw moving sphere in a smooth way in C# 在C#中,基于解析输入字符串来控制流的最佳方法是什么 - In C#, what is the best way to control flow based on parsing an input string C#:控制中的Direct3D,辅助监视器上的全屏 - 最好的方法是什么? - C# : Direct3D in a control, AND fullscreen on a secondary monitor - what's the best way? 进行无闪烁动画C#自定义控件的最佳方法是什么? - What is the best way to do a flicker-free animated C# custom control? 操作方法:在控制台应用程序中绘制表格的最佳方法 (C#) - How To: Best way to draw table in console app (C#) 不使用画布C#绘制线条的最佳方法 - Best way to draw a line without using a canvas C#
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM