




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 敬老院五保户合同协议书
- 木工承包合同协议书
- 物流公司劳务合同协议书
- 离职协议合同协议书
- 松树的承包合同协议书
- 艺术培训服务合同协议书
- 贷款合同协议书
- 爆破合同协议书范本
- 场地项目经理合同协议书
- 地板打蜡合同协议书范本
- (三诊)成都市2022级高中高三毕业班第三次诊断性检物理试卷(含答案)
- 四川省成都市蓉城名校联盟2024-2025学年高一下学期期中考试英语(含答案)
- 2025-2030中国户外背包行业市场发展趋势与前景展望战略研究报告
- 2025广东二模语文(含答案)
- 建投国电准格尔旗能源有限公司招聘考试真题2024
- 农行反洗钱与制裁合规知识竞赛考试题库大全-上下
- 2025年上半年陕西西安阎良区事业单位招聘高层次及紧缺特殊专业人才9人重点基础提升(共500题)附带答案详解
- 《高压输电线路巡检维护合同》
- 《中国古典文学中的咏鱼诗与生态文化》论文
- 商品混凝土管理制度
- 2025年中考数学几何模型综合训练专题16全等三角形模型之婆罗摩笈多模型解读与提分精练(教师版)
评论
0/150
提交评论