C#下实现双缓冲描画高频曲线(GDI+结合GDI)

由于项目需要,要使用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 = pictureBox1;

            lock (_backgroundGraph)
            {
                if (null != _backgroundGraphic)
                {
                    _backgroundGraphic.Dispose();
                }

                if (null != _graphicsBuffer)
                {
                    _graphicsBuffer.Dispose();
                }

                if (null != _backgroundRenderGraphic)
                {
                    _backgroundRenderGraphic.Dispose();
                }

                if (null != _backgroundMemoryBitmap)
                {
                    DeleteObject(_memoryBitmapHdc);
                    _backgroundMemoryBitmap.Dispose();
                }

                if (null != _backgroundMemoryGraphic)
                {
                    DeleteObject(_memoryGraphicHdc);
                    _backgroundMemoryGraphic.Dispose();
                }

                if (null != _backgroundDrawGraphic)
                {
                    _backgroundDrawGraphic.Dispose();
                }

                // 背景Graphic
                _backgroundGraphic = _backgroundGraph.CreateGraphics();

                BufferedGraphicsContext currentContext = BufferedGraphicsManager.Current;
                _graphicsBuffer = currentContext.Allocate(_backgroundGraphic, _backgroundGraph.ClientRectangle);

                // 双缓冲Graphic
                _backgroundRenderGraphic = _graphicsBuffer.Graphics;
                _backgroundRenderGraphic.Clear(Color.White);

                _backgroundRenderGraphic.SetClip(_backgroundGraph.ClientRectangle);

                // 内存Bitmap
                _backgroundMemoryBitmap = new Bitmap(_backgroundGraph.ClientRectangle.Width * 10, _backgroundGraph.ClientRectangle.Height, _backgroundRenderGraphic);

                // 内存Graphic
                _backgroundMemoryGraphic = Graphics.FromImage(_backgroundMemoryBitmap);
                _backgroundMemoryGraphic.Clear(Color.White);

                // 创建适用的绘图区
                _memoryGraphicHdc = CreateCompatibleDC(_backgroundMemoryGraphic.GetHdc());
                _memoryBitmapHdc = _backgroundMemoryBitmap.GetHbitmap();

                SelectObject(_memoryGraphicHdc, _memoryBitmapHdc);

                // 描画Graphic
                _backgroundDrawGraphic = Graphics.FromHdc(_memoryGraphicHdc);

                _backgroundDrawGraphic.SmoothingMode = SmoothingMode.HighQuality;
                _backgroundDrawGraphic.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
                _backgroundDrawGraphic.InterpolationMode = InterpolationMode.HighQualityBilinear;
                _backgroundDrawGraphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
            }
        }
4.使用GDI+描画曲线

 public void DrawSomething()
        {
            _backgroundDrawGraphic.DrawLine(System.Drawing.Pens.Black, 0, 0, 100, 100);

        }
5.使用bitblt向前台描画

   public void UpdateView()
        {
            IntPtr memHdc = _backgroundDrawGraphic.GetHdc();
            IntPtr renHdc = _backgroundRenderGraphic.GetHdc();

            BitBlt(renHdc, 0, 0, 100,
            100, memHdc, 0, 0, 0xCC0020);

            _backgroundDrawGraphic.ReleaseHdc();
            _backgroundRenderGraphic.ReleaseHdc();

            _graphicsBuffer.Render(_backgroundGraphic);
        }
 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/fanerde/archive/2008/10/24/3136670.aspx

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值