由於專案需要,要使用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()
if (null != _graphicsbuffer)
if (null != _backgroundrendergraphic)
if (null != _backgroundmemorybitmap)
if (null != _backgroundmemorygraphic)
if (null != _backgrounddrawgraphic)
// 背景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()
5.使用bitblt向前臺描畫
public
void updateview()
C 實現雙緩衝
1 在記憶體中申請緩衝區,建立相容記憶體 2 建立位圖,並將點陣圖與緩衝區記憶體相關聯起來 3 在相容記憶體裡繪製 4 將繪製好的點陣圖拷貝到當前裝置 5 釋放相容記憶體。cpoint ptcenter crect rect,ellipserect getclientrect rect ptcent...
C 實現雙緩衝
首先宣告下,這篇資料也是整理別人的資料的基礎上,總結來的。在圖形影象處理過程中,雙緩衝技術是一種比較常見的技術。窗體在響應wm paint訊息時,需要對影象進行繪製處理。如果影象繪製次數過多,重繪過於頻繁時,或者當要繪製的物件太複雜,尤其是含有點陣圖時,一般計算機便力不從心了。顯示器上就會因為重新整...
mfc下實現雙緩衝的方法
本帖解決的問題 如何實現雙緩衝 為什麼實現了雙緩衝還是會閃爍?以下資料為本人積累和加上自己的經驗 1 簡介一下windows mfc的view顯示重新整理過程 1 使用背景刷填充view窗體 呼叫內在機制的 2 呼叫onpain ondraw 呼叫使用者的 2 產生閃爍的原因出在於 當我們很快地重新...