高效使用OnPaint
我正在 Visual Studio .Net 中使用 C# 进行编程。
我正在创建自己的控件,该控件根据从模数转换器 (ADC) 获得的值绘制波形。我将传入的点转换为 X 和 Y 点,以便在我的控制中正确绘制图形。
我的 OnPaint 方法中有一个循环,它遍历所有点并调用当前点和下一个点之间的 DrawLine 方法。
然而,这是非常低效的,因为其中一些图表有 8192 个点,而系统实际上有 9 个我想同时显示的 ADC。每次页面重绘时,所有图形都需要几乎一秒钟的时间来重绘(尤其是在调试期间)。
最重要的是,我的功能允许您放大和平移波浪以获得更好的视图(其作用很像谷歌地图),并且所有 9 个波浪一起放大和平移。
所有这些功能都非常“不稳定”,因为我在鼠标滚轮和鼠标移动上调用无效。基本上,这一切都有效,但并不像我希望的那么顺利。
我想知道是否有一种方法可以从数据创建预绘制对象,然后在绘图区域中绘制图片的放大和平移版本。
任何帮助将不胜感激,即使它只是为我指明了正确的方向。
I am programming in Visual Studio .Net and using C#.
I am creating my own control that draws a wave based on values I get from an analog to digital converter (ADC). I take the incoming points and convert them into X and Y points to properly draw the graph in my control.
I have a loop inside my OnPaint method that goes through all the points and calls the DrawLine method between the current point and the next point.
However, this is very inefficient as some of these graphs have 8192 points and the system actually has nine ADCs that I would like to show at the same time. Every time the page redraws it takes almost a second for all graphs to redraw (especially during debug).
On top of that, I have functionality that allows you to zoom in and pan across the waves to get a better view (acts a lot like google maps does) and all 9 waves zoom in and pan together.
All of this functionality is very "jerky" because I am calling invalidate on mousewheel and mousemove. Basically, it all works but not as smoothly as I would like.
I was wondering if there were a way to create a predrawn object from the data and then just draw a dilated and translated version of the picture in the draw area.
Any help would be greatly appreciated even if it is just pointing me in the right direction.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
创建一个 Bitmap 对象,然后绘制到该对象。
在您的 Paint 处理程序中,只需将位图传输到屏幕即可。
这将允许您将更改比例与重新渲染数据分离。
Create a Bitmap object, and draw to that.
In your Paint handler, just blit the Bitmap to the screen.
That will allow you decouple changing the scale, from re-rendering the data.
您可以在控件/表单上将
DoubleBuffered
设置为 true。或者您可以尝试使用自己的图像来创建双缓冲效果。我的
DoubleBufferedGraphics
类:在
OnPaint
中使用它:ControlStyles 如果我使用它,我通常会设置它(您可能有不同的需求):
编辑:
好吧,由于数据是静态的,您应该绘制到图像(在 OnPaint 之前),然后在 OnPaint 中使用
Graphics.DrawImage()
重载将源图像的正确区域绘制到屏幕上。如果数据没有改变,就没有理由重新绘制线条。You might set
DoubleBuffered
to true on your control / form. Or you could try using your own Image to create a double buffered effect.My
DoubleBufferedGraphics
class:Using it in an
OnPaint
:ControlStyles I generally set if I'm using it (you may have different needs):
Edit:
Ok since the data is static you should paint to an Image (before your OnPaint) and then in the OnPaint use the
Graphics.DrawImage()
overload to draw the correct region of your source image to the screen. No reason to redraw the lines if the data isn't changing.我补充两点:
这样,您将避免使用静态位图(以允许缩放),同时仍然获得一些性能改进。
I have two points to add:
This way you'll avoid using static bitmap (to allow zooming) while still getting some performance improvements.
你可以画一条多线。我不确定它在 C# 中是什么样子,但它必须存在(它是基于 GDI/GDI+ 的 API)。这允许您一次性指定所有点,并允许 Windows 稍微优化调用(更少的堆栈推送/弹出保留在绘制算法中,而不是返回每个新点的代码)。
编辑:但是如果您的数据是静态的,那么使用输出的双缓冲/缓存图像比担心它的初始绘制更有效。
这是一个链接:http://msdn.microsoft。 com/en-us/library/system.windows.shapes.polyline.aspx
You could draw a multiline. I'm not sure what that looks like in C#, but it has to be there (Its a GDI/GDI+ based API). That allows you specify all the points in one go, and allows Windows to optimize the call a bit (less stack push/pop to stay inside of the draw algorithm rather than returning to your code for each new point).
EDIT: but if your data is static, then using a double buffered / cached image of your output is more efficient than worrying about the initial drawing of it.
Here's a link: http://msdn.microsoft.com/en-us/library/system.windows.shapes.polyline.aspx
只需计算可见范围并仅绘制这些点即可。
使用双缓冲。最后,您可以使用原始位图数据创建自己的多线绘制实现,例如使用 LockBits 并将像素颜色直接写入形成图片的字节中。使用 InvalidateRect(..) 重绘窗口的一部分。
Just calculate the visible range and draw only these points.
Use double buffering. And finally you can create you own realizaion of multiline drawing using raw bitmap data e.g. use LockBits and write pixel colors directly into bytes forming the picture.Use InvalidateRect(..) to redraw a portion of the window.