




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第WPF+WriteableBitmap實現(xiàn)高性能曲線圖的繪制目錄一、前言二、正文三、運(yùn)行效果
一、前言
之前分享過一期關(guān)于DrawingVisual來繪制高性能曲線的博客,今天再分享一篇通過另一種方式來繪制高性能曲線的方法,也就是通過WriteableBitmap的方式;具體的一些細(xì)節(jié)這里就不啰嗦了,同樣是局部繪制的思想,滾動條拖動到哪里,就只繪制那一部分的曲線,直接貼代碼;(該程序在英特爾11代CPU的電腦可能會遇到拖動滾動條曲線圖卡住不動的情況,這個是顯卡驅(qū)動的問題,官方已經(jīng)修復(fù)了,遇到這問題的記得更新一下驅(qū)動)
二、正文
1、新建一個類,繼承FrameworkElement,然后在里面實現(xiàn)一下繪圖的邏輯;
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Drawing;
usingSystem.Drawing.Drawing2D;
usingSystem.Drawing.Text;
usingSystem.IO;
usingSystem.Windows;
usingSystem.Windows.Media;
usingSystem.Windows.Media.Imaging;
usingSystem.Windows.Resources;
using_Font=System.Drawing.Font;
usingGDI=System.Drawing;
namespaceWriteableBitmapDemo.Controls
publicclassCruveWriteableBitmap:FrameworkElement
privatestaticPrivateFontCollectionpfc=newPrivateFontCollection();
privateWriteableBitmapbitmap;
privateintbitmap_width=0;
privateintbitmap_height=0;
privatestatic_Fontfont=null;
privatestatic_Fonttime_font=null;
privatePointF[][]horizontals=null;
privatePointF[][]horizontals_thin=null;
privatePointF[][]verticals=null;
privatePointF[][]verticals_thin=null;
privateListPointFtop_points1;
privateListPointFtop_points2;
privateListPointFtop_points3;
privateListPointFbottom_points;
privateListPointFlabelPosition_up;
privateListstringlabelText_up;
privateListPointFlabelPosition_down;
privateListstringlabelText_down;
privateListPointFtimePosition;
privateListstringtimeText;
privateGDI.PenblackPen=newGDI.Pen(GDI.Color.Black,1.5f);
privateGDI.PengrayPen=newGDI.Pen(GDI.Color.Gray,1f);
privateGDI.Pentop_pen1=newGDI.Pen(GDI.Color.Black,2);
privateGDI.Pentop_pen2=newGDI.Pen(GDI.Color.Orange,2);
privateGDI.Pentop_pen3=newGDI.Pen(GDI.Color.Purple,2);publicfloatscaleX{get;set;}=1f;
privatefloat_ScaleY{get;set;}=1f;
publicfloatScaleY
get{return_ScaleY;}
_ScaleY=value;
staticCruveWriteableBitmap()
varappRootDataDir=Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"msyh.ttf");
if(!File.Exists(appRootDataDir))
varkey=$"/CurveChartDemo;component/Fonts/msyh.ttf";
StreamResourceInfoinfo=Application.GetResourceStream(newUri(key,UriKind.Relative));
using(varstream=info.Stream)
byte[]bytes=newbyte[stream.Length];
intlen=stream.Read(bytes,0,bytes.Length);
File.WriteAllBytes(appRootDataDir,bytes);
pfc.AddFontFile(appRootDataDir);
publicCruveWriteableBitmap()
time_font=new_Font(pfc.Families[0],10);
font=new_Font(pfc.Families[0],8);
publicvoidDrawPoints()
//InitBitmap();
if(this.bitmap==null)
return;
this.bitmap.Lock();
using(BitmapbackBufferBitmap=newBitmap(this.bitmap_width,this.bitmap_height,
this.bitmap.BackBufferStride,GDI.Imaging.PixelFormat.Format24bppRgb,
this.bitmap.BackBuffer))
using(GraphicsbackBufferGraphics=Graphics.FromImage(backBufferBitmap))
backBufferGraphics.SmoothingMode=SmoothingMode.AntiAlias;
backBufferGraphics.CompositingQuality=CompositingQuality.HighSpeed;
backBufferGraphics.Clear(GDI.Color.White);
//粗橫線
if(this.horizontals!=null)
foreach(varhorizontalinthis.horizontals)
backBufferGraphics.DrawLine(blackPen,horizontal[0],horizontal[1]);
//細(xì)橫線
if(this.horizontals_thin!=null)
foreach(varhorizontalinthis.horizontals_thin)
backBufferGraphics.DrawLine(grayPen,horizontal[0],horizontal[1]);
//粗豎線
if(this.verticals!=null)
foreach(varverticalinthis.verticals)
backBufferGraphics.DrawLine(blackPen,vertical[0],vertical[1]);
//細(xì)豎線
if(this.verticals_thin!=null)
foreach(varverticalinthis.verticals_thin)
backBufferGraphics.DrawLine(grayPen,vertical[0],vertical[1]);
//上圖曲線1
if(this.top_points1!=nullthis.top_points1.Count0)
backBufferGraphics.DrawLines(top_pen1,top_points1.ToArray());
//上圖曲線2
if(this.top_points2!=nullthis.top_points2.Count0)
backBufferGraphics.DrawLines(top_pen2,this.top_points2.ToArray());
//上圖曲線3
if(this.top_points3!=nullthis.top_points3.Count0)
backBufferGraphics.DrawLines(top_pen3,this.top_points3.ToArray());
//下圖曲線
if(this.bottom_points!=nullthis.bottom_points.Count0)
backBufferGraphics.DrawLines(top_pen1,this.bottom_points.ToArray());
//文本
if(labelPosition_up!=nulllabelPosition_up.Count0)
SizeFfontSize=backBufferGraphics.MeasureString(labelText_up[0],font);
for(inti=0;ilabelPosition_up.Count;++i)
backBufferGraphics.DrawString(labelText_up[i],font,GDI.Brushes.Black,labelPosition_up[i].X,labelPosition_up[i].Y-fontSize.Height);
if(labelPosition_down!=nulllabelPosition_down.Count0)
for(inti=0;ilabelPosition_down.Count;++i)
backBufferGraphics.DrawString(labelText_down[i],font,GDI.Brushes.Black,labelPosition_down[i].X,labelPosition_down[i].Y);
if(timePosition!=nulltimePosition.Count0)
for(inti=0;itimePosition.Count;++i)
if(i==0)
backBufferGraphics.DrawString(timeText[i],time_font,GDI.Brushes.Black,timePosition[i].X,timePosition[i].Y);
else
SizeFfontSize=backBufferGraphics.MeasureString(timeText[i],time_font);
backBufferGraphics.DrawString(timeText[i],time_font,GDI.Brushes.Black,timePosition[i].X-fontSize.Width/2,timePosition[i].Y);
backBufferGraphics.Flush();
this.bitmap.AddDirtyRect(newInt32Rect(0,0,this.bitmap_width,this.bitmap_height));
this.bitmap.Unlock();
}publicvoidUpdateTimeLabel(ListPointFtimePosition,ListstringtimeText)
this.timePosition=timePosition;
this.timeText=timeText;
publicvoidUpdatePosition(ListPointFfhr1_points,ListPointFfhr2_points,ListPointFfhr3_points,ListPointFtoco_points)
this.top_points1=fhr1_points;
this.top_points2=fhr2_points;
this.top_points3=fhr3_points;
this.bottom_points=toco_points;
publicvoidUpdateLabelPosition(ListPointFlabelPosition_up,ListstringlabelText_up,ListPointFlabelPosition_down,ListstringlabelText_down)
this.labelPosition_up=labelPosition_up;
this.labelText_up=labelText_up;
this.labelPosition_down=labelPosition_down;
this.labelText_down=labelText_down;
publicvoidUpdateHorizontalLine(PointF[][]horizontals,PointF[][]horizontals_thin)
this.horizontals=horizontals;
this.horizontals_thin=horizontals_thin;
publicvoidUpdateVerticalLine(PointF[][]verticals,PointF[][]verticals_thin)
this.verticals=verticals;
this.verticals_thin=verticals_thin;
protectedoverridevoidOnRender(DrawingContextdc)
InitBitmap();
if(this.bitmap!=null)
dc.DrawImage(bitmap,newRect(0,0,RenderSize.Width,RenderSize.Height));
base.OnRender(dc);
privatevoidInitBitmap()
if(bitmap==null||this.bitmap.Width!=(int)this.ActualWidth||this.bitmap.Height!=(int)this.ActualHeight)
if((int)this.ActualWidth0(int)this.ActualHeight0)
this.bitmap_width=(int)this.ActualWidth;
this.bitmap_height=(int)this.ActualHeight;
this.bitmap=newWriteableBitmap(bitmap_width,bitmap_height,96,96,PixelFormats.Bgr24,null);
this.bitmap.Lock();
using(BitmapbackBufferBitmap=newBitmap(bitmap_width,bitmap_height,
this.bitmap.BackBufferStride,GDI.Imaging.PixelFormat.Format24bppRgb,
this.bitmap.BackBuffer))
using(GraphicsbackBufferGraphics=Graphics.FromImage(backBufferBitmap))
backBufferGraphics.SmoothingMode=SmoothingMode.HighSpeed;
backBufferGraphics.CompositingQuality=CompositingQuality.HighSpeed;
backBufferGraphics.Clear(GDI.Color.White);
backBufferGraphics.Flush();
this.bitmap.AddDirtyRect(newInt32Rect(0,0,bitmap_width,bitmap_height));
this.bitmap.Unlock();
}
2、主窗口添加該控件,并添加滾動條那些
Window
x:xmlns="/winfx/2006/xaml/presentation"
xmlns:x="/winfx/2006/xaml"
xmlns:ct="clr-namespace:WriteableBitmapDemo.Controls"
xmlns:d="/expression/blend/2008"
xmlns:local="clr-namespace:WriteableBitmapDemo"
xmlns:mc="/markup-compatibility/2006"
Title="MainWindow"
Width="1500"
Height="450"
Loaded="Window_Loaded"
mc:Ignorable="d"
Grid
ct:CruveWriteableBitmapx:Name="curve"Margin="0,0,0,20"/
ScrollViewer
Name="scroll"
HorizontalScrollBarVisibility="Auto"
ScrollChanged="ScrollViewer_ScrollChanged"
VerticalScrollBarVisibility="Disabled"
Canvasx:Name="canvas"Height="1"/
/ScrollViewer
Canvas
x:Name="CanvasPanel"
Margin="0,0,0,20"
Background="Transparent"/
/Grid
/Window
3、主窗口后臺添加曲線數(shù)值生成方法和更新視圖數(shù)據(jù)方法
usingSystem.Collections.Generic;
usingSystem.Drawing;
usingSystem.Windows;
usingSystem.Windows.Controls;
usingSystem.Windows.Input;
namespaceWriteableBitmapDemo
///summary
///MainWindow.xaml的交互邏輯
////summary
publicpartialclassMainWindow:Window
privateboolisAdd=true;
privateDictionaryint,intdicTopPoints=newDictionaryint,int
privateDictionaryint,intdicBottomPoints=newDictionaryint,int
privatefloaty_scale;
privatestaticintTop_Val_Max=240;
privatestaticintTop_Val_Min=30;
privatestaticintTop_X_Sex=20;
privatestaticintBottom=100;
privatestaticintCenter=25;
privatestaticintBottomOffset=0;
privatedoubleoffset=-1;
publicMainWindow()
InitializeComponent();
CanvasPanel.MouseMove+=delegate(objectsender,MouseEventArgse)
if(e.LeftButton==MouseButtonState.Pressed)
if(Mouse.Captured==null)Mouse.Capture(CanvasPanel);
if(offset=0offset=CanvasPanel.ActualWidth)
scroll.ScrollToHorizontalOffset(scroll.HorizontalOffset-(e.GetPosition(this).X-offset));
offset=e.GetPosition(this).X;
else
offset=-1;
Mouse.Capture(null);//釋放鼠標(biāo)捕獲
privatevoidWindow_Loaded(objectsender,RoutedEventArgse)
//生成曲線數(shù)據(jù)
inttemp=50;
for(inti=0;i24*60*60*4;i++)
if(isAdd)
dicTopPoints.Add(i,temp);
temp+=2;
else
dicTopPoints.Add(i,temp);
temp-=2;
if(temp==210)isAdd=false;
if(temp==50)isAdd=true;
temp=0;
for(inti=0;i24*60*60*4;i++)
if(isAdd)
dicBottomPoints.Add(i,temp);
temp+=2;
else
dicBottomPoints.Add(i,temp);
temp-=2;
if(temp==100)isAdd=false;
if(temp==0)isAdd=true;
//初始化滾動條和觸發(fā)曲線繪制
canvas.Width=dicTopPoints.Count;
scroll.ScrollToLeftEnd();
privatevoidScrollViewer_ScrollChanged(objectsender,ScrollChangedEventArgse)
InitChartData((float)scroll.HorizontalOffset);
///summary
///根據(jù)滾動條偏移量更新需要繪制的數(shù)據(jù)
////summary
///paramname="offset"/param
privatevoidInitChartData(floatoffset)
y_scale=(float)((curve.ActualHeight-Center)/(Top_Val_Max-Top_Val_Min+Bottom));
//上圖橫線
ListPointF[]horizontalList=newListPointF[]
ListPointF[]horizontalList_thin=newListPointF[]
for(inty=0;y=Top_Val_Max-Top_Val_Min;y+=10)
floatcurrentHeight=(float)(curve.ActualHeight-(y+Bottom)*y_scale-Center);
PointFpoint1=newPointF(0,currentHeight);
PointFpoint2=newPointF((float)curve.ActualWidth,currentHeight);
if(y%30==0)
horizontalList.Add(newPointF[]{point1,point2});
else
horizontalList_thin.Add(newPointF[]{point1,point2});
for(inty=0;y=Bottom;y+=10)
floatcurrentHeight=(float)(curve.ActualHeight-y*y_scale-BottomOffset);
PointFpoint1=newPointF(0,currentHeight);
PointFpoint2=newPointF((float)curve.ActualWidth,currentHeight);
if(y%20==0)
horizontalList.Add(newPointF[]{point1,point2});
else
horizontalList_thin.Add(newPointF[]{point1,point2});
//豎線與文字
ListPointF[]verticals=newListPointF[]
ListPointF[]verticals_thin=newListPointF[]
ListPointFtimePosition=newListPointF
ListstringtimeText=newListstring
ListPointFlabelPosition_up=newListPointF
ListstringlabelText_up=newListstring
ListPointFlabelPosition_down=newListPointF
ListstringlabelText_down=newListstring
for(inti=0;ioffset+curve.ActualWidth;i+=Top_X_Sex*2)
if(ioffset)continue;
//下豎線
PointFpoint1=newPointF(i-offset,(float)(curve.ActualHeight-BottomOffset));
PointFpoint2=newPointF(i-offset,(float)(curve.ActualHeight-Bottom*y_scale-BottomOffset));
//上豎線
PointFpoint3=newPointF(i-offset,0);
PointFpoint4=newPointF(i-offset,(float)(curve.ActualHeight-Bottom*y_scale-Center));
if((i+(60*2))%(60*2)==0)
verticals.Add(newPointF[]{point1,point2});
verticals.Add(newPointF[]{point3,point4});
else
verticals_thin.Add(newPointF[]{point1,point2});
verticals_thin.Add(newPointF[]{point3,point4});
if(i%240==0)
timeText.Add(i+"");
timePosition.Add(newPointF(i-offset,(float)(curve.ActualHeight-Bottom*y_scale-Center)));
if((i+(60*2))%(120*2)==0)
for(inty=Top_Val_Min;y=Top_Val_Max;y+=10)
if(y%30==0)
labelText_up.Add(y+"");
labelPosition_up.Add(newPointF(i-offset,(float)(curve.ActualHeight-(Bottom+y-Top_Val_Min)*y_scale-Center)));
for(inty=20;y=100;y+=10)
if(y%20==0)
labelText_down.Add(y+"");
labelPosition_down.Add(newPointF(i-offset,(float)(curve.ActualHeight-y*y_scale)));
ListPointFtop_points1=newListPointF
for(int
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 橙色可愛卡通節(jié)約糧食模板
- 股權(quán)轉(zhuǎn)讓協(xié)議
- 產(chǎn)品業(yè)務(wù)提成合同范例
- 人事部經(jīng)理工作總結(jié)模版
- 醫(yī)療健康大數(shù)據(jù)驅(qū)動的個性化醫(yī)療解決方案
- 2025年小學(xué)體育教師年度考核個人工作總結(jié)模版
- 運(yùn)輸新質(zhì)生產(chǎn)力
- 預(yù)留、預(yù)埋、防雷等施工技術(shù)總結(jié)
- 中藥柜銷售合同范例
- 醫(yī)院科室質(zhì)控工作總結(jié)模版
- 歷史一戰(zhàn)二戰(zhàn)試卷及答案
- 2025年導(dǎo)游從業(yè)資格知識點合輯
- (三診)成都市2022級高中高三畢業(yè)班第三次診斷性檢物理試卷(含答案)
- 四川省成都市蓉城名校聯(lián)盟2024-2025學(xué)年高一下學(xué)期期中考試英語(含答案)
- 2025-2030中國戶外背包行業(yè)市場發(fā)展趨勢與前景展望戰(zhàn)略研究報告
- 2025廣東二模語文(含答案)
- 建投國電準(zhǔn)格爾旗能源有限公司招聘考試真題2024
- 農(nóng)行反洗錢與制裁合規(guī)知識競賽考試題庫大全-上下
- 2025年上半年陜西西安閻良區(qū)事業(yè)單位招聘高層次及緊缺特殊專業(yè)人才9人重點基礎(chǔ)提升(共500題)附帶答案詳解
- 《高壓輸電線路巡檢維護(hù)合同》
- 2025年中考數(shù)學(xué)幾何模型綜合訓(xùn)練專題16全等三角形模型之婆羅摩笈多模型解讀與提分精練(教師版)
評論
0/150
提交評論