C#下實現雙緩沖描畫高頻曲線(GDI+結合GDI)

http://blog.csdn.net/fanerde/article/details/3136670

由於項目需要,要使用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+描畫曲線

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


你可能感兴趣的:(api,C#,null,buffer,GDI+)