由于项目需要,要使用c#描画高频实时曲线.
但是在C#下由于描画图像使用的是GDI+,描画效率很有问题.一旦曲线太多,就会造成CPU使用率直线上升,马上飙升到100%.
在GDI+下使用双缓冲也无济于事,双缓冲本身只会解决曲线多的时候全屏闪烁问题,但描画效率还是严重低下.
其间用过多种解决方案:DRECT3D,DRIRECT2D,GDI,,,,,等等等等
最后从效率出发,最终解决方案如下:
前台显示使用GDI,而后台描画则采用GDI+
后台采用10倍于前台窗口的BUFFER,每次向其中画一条线.然后通过一个RECT视口,每次向前台显示视口里的内容.否则每次重绘的代价太高.
这个方法实现的难点主要在于GDI和GDI+的结合部分,主要代码如下:
1.函数库:using 和 WIN32API函数
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
[DllImport("gdi32")]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32")]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hObject);
[DllImport("GDI32.dll")]
public static extern long BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop);
[DllImport("GDI32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
2.声明对象
public PictureBox _backgroundGraph;//被描画的控件对象
//public Form _backgroundGraph;
public Graphics _backgroundGraphic = null; // 背景Graphic
public Graphics _backgroundRenderGraphic = null; // 双缓冲Graphic
private Graphics _backgroundMemoryGraphic = null; // 内存Graphic
public Graphics _backgroundDrawGraphic = null; // 描画Graphic
private Bitmap _backgroundMemoryBitmap = null; // 内存Bitmap
public BufferedGraphics _graphicsBuffer = null; // 双缓冲BufferedGraphics
private IntPtr _memoryGraphicHdc; // 内存Graphic适用的引用
private IntPtr _memoryBitmapHdc; // 内存Bitmap适用的引用
3.初始化对象
public void InitDraw()
{
_backgroundGraph = pictu