WPF+WriteableBitmap实现高性能曲线图的绘制_第1页
WPF+WriteableBitmap实现高性能曲线图的绘制_第2页
WPF+WriteableBitmap实现高性能曲线图的绘制_第3页
WPF+WriteableBitmap实现高性能曲线图的绘制_第4页
WPF+WriteableBitmap实现高性能曲线图的绘制_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第WPF+WriteableBitmap实现高性能曲线图的绘制目录一、前言二、正文三、运行效果

一、前言

之前分享过一期关于DrawingVisual来绘制高性能曲线的博客,今天再分享一篇通过另一种方式来绘制高性能曲线的方法,也就是通过WriteableBitmap的方式;具体的一些细节这里就不啰嗦了,同样是局部绘制的思想,滚动条拖动到哪里,就只绘制那一部分的曲线,直接贴代码;(该程序在英特尔11代CPU的电脑可能会遇到拖动滚动条曲线图卡住不动的情况,这个是显卡驱动的问题,官方已经修复了,遇到这问题的记得更新一下驱动)

二、正文

1、新建一个类,继承FrameworkElement,然后在里面实现一下绘图的逻辑;

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]);

//细横线

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]);

//细竖线

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、主窗口后台添加曲线数值生成方法和更新视图数据方法

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);//释放鼠标捕获

privatevoidWindow_Loaded(objectsender,RoutedEventArgse)

//生成曲线数据

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;

//初始化滚动条和触发曲线绘制

canvas.Width=dicTopPoints.Count;

scroll.ScrollToLeftEnd();

privatevoidScrollViewer_ScrollChanged(objectsender,ScrollChangedEventArgse)

InitChartData((float)scroll.HorizontalOffset);

///summary

///根据滚动条偏移量更新需要绘制的数据

////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. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论