wpF 使用 DrawingContext 绘制温度计
框架使用大于等于.NET40
;
Visual Studio 2022;
项目使用 MIT 开源许可协议;
定义Interval
步长、MaxValue
最大温度值、MinValue
最小温度值。
CurrentGeometry
重新绘制当前刻度的Path
值。
CurrentValue
当前值如果发生变化时则去重新CurrentGeometry
。
OnRender
绘制如下
RoundedRectangle
温度计的外边框。- 使用方法
DrawText
单字绘制华氏温度
文本Y
轴变化。 - 使用方法
DrawText
单字绘制摄氏温度
文本Y
轴变化。 - 使用方法
DrawText
绘制温度计两侧的刻度数值。 - 使用方法
DrawLine
绘制温度计两侧的刻度线。
实现代码
1) 准备Thermometer.cs如下:
usingSystem; usingSystem.Windows; usingSystem.Windows.Controls; usingSystem.Windows.Media; namespaceWPFDevelopers.Controls { publicclassThermometer:Control smLmCTsI{ publicstaticreadonhttp://www.devze.comlyDependencyPropertyMaxValueProperty= DependencyProperty.Register("MaxValue",typeof(double),typeof(Thermometer),newUIPropertyMetadata(40.0)); publicstaticreadonlyDependencyPropertyMinValueProperty= DependencyProperty.Register("MinValue",typeof(double),typeof(Thermometer),newUIPropertyMetadata(-10.0)); ///<summary> ///当前值 ///</summary> publicstaticreadonlyDependencyPropertyCurrentValueProperty= DependencyProperty.Register("CurrentValue",typeof(double),typeof(Thermometer), newUIPropertyMetadata(OnCurrentValueChanged)); ///<summary> ///步长 ///</summary> publicstaticreadonlyDependencyPropertyIntervalProperty= DependencyProperty.Register("Interval",typeof(double),typeof(Thermometer),newUIPropertyMetadata(10.0)); ///<summary> ///当前值的图形坐标点 ///</summary> publicstaticreadonlyDependencyPropertyCurrentGeometryProperty= DependencyProperty.Register("CurrentGeometry",typeof(Geometry),typeof(Thermometer),newPropertyMetadata( Geometry.Parse(@"M2132.8 a440014-4 h18 a4400144 v32.2 a44001-44 h-18 a44001-4-4z"))); ///<summary> ///构造函数 ///</summary> staticThermometer() { DefaultStyleKeyProperty.OverrideMetadata(typeof(Thermometer), nejswFrameworkPropertyMetadata(typeof(Thermometer))); } publicdoubleMaxValue { get=>(double)GetValue(MaxValueProperty); set=>SetValue(MaxValueProperty,value); } publicdoubleMinValue { get=>(double)GetValue(MinValueProperty); set=>SetValue(MinValueProperty,value); } publicdoubleCurrentValue { get=>(double)GetValue(CurrentValueProperty); set { SetValue(CurrentValueProperty,value); PaintPath(); } } publicdoubleInterval { get=>(double)GetValue(IntervalProperty); set=>SetValue(IntervalProperty,value); } publicGeometryCurrentGeometry { get=>(Geometry)GetValue(CurrentGeometryProperty); set=>SetValue(CurrentGeometryProperty,value); } privatestaticvoidOnCurrentValueChanged(DependencyObjectd,DependencyPropertyChangedEventArgse) { varthermometer=dasThermometer; thermometer.CurrentValue=Convert.ToDouble(e.NewValue); } publicoverridevoidOnApplyTemplate() { base.OnApplyTemplate(); PaintPath(); } protectedoverridevoidOnRender(DrawingContextdrawingContext) { varbrush=newSolidColorBrush((Color)ColorConverter.ConvertFromString("#82848A")); varrect=newRect(); rect.Width=30; rect.Height=169; drawingContext.DrawRoundedRectangle(Brushes.Transparent, newPen(brush,2d), rect,8d,8d); #region华氏温度 drawingContext.DrawText( DrawingContextHelper.GetFormattedText("华", (Brush)DrawingContextjsHelper.BrushConverter.ConvertFromString("#82848A"),textSize:14D), newPoint(-49,115)); drawingContext.DrawText( DrawingContextHelper.GetFormattedText("氏", (Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),textSize:14D), newPoint(-49,115+14)); drawingContext.DrawText( DrawingContextHelper.GetFormattedText("温", (Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),textSize:14D), newPoint(-49,115+28)); drawingContext.DrawText( DrawingContextHelper.GetFormattedText("度", (Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),textSize:14D), newPoint(-49,115+42)); #endregion #region摄氏温度 drawingContext.DrawText( DrawingContextHelper.GetFormattedText("摄", (Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),FlowDirection.LeftToRight, 14D),newPoint(75,115)); drawingContext.DrawText( DrawingContextHelpe开发者_开发学习r.GetFormattedText("氏", (Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),FlowDirection.LeftToRight, 14D),newPoint(75,115+14)); drawingContext.DrawText( DrawingContextHelper.GetFormattedText("温", (Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),FlowDirection.LeftToRight, 14D),newPoint(75,115+28)); drawingContext.DrawText( DrawingContextHelper.GetFormattedText("度", (Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),FlowDirection.LeftToRight, 14D),newPoint(75,115+42)); #endregion #region画刻度 vartotal_Value=MaxValue-MinValue; varcnt=total_Value/Interval; varone_value=161d/cnt; for(vari=0;i<=cnt;i++) { varformattedText=DrawingContextHelper.GetFormattedText($"{MaxValue-i*Interval}", (Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),FlowDirection.LeftToRight, 14D); drawingContext.DrawText(formattedText, newPoint(43,i*one_value-formattedText.Height/2d));//减去字体高度的一半 formattedText=DrawingContextHelper.GetFormattedText($"{(MaxValue-i*Interval)*1.8d+32d}", (Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),textSize:14D); drawingContext.DrawText(formattedText,newPoint(-13,i*one_value-formattedText.Height/2d)); if(i!=0&&i!=5) { drawingContext.DrawLine(newPen(Brushes.Black,1d), newPoint(4,i*one_value),newPoint(6,i*one_value)); drawingContext.DrawLine(newPen(Brushes.Black,1d), newPoint(24,i*one_value),newPoint(26,i*one_value)); } } #endregion } ///<summary> ///动态计算当前值图形坐标点 ///</summary> privatevoidPaintPath() { varone_value=161d/((MaxValue-MinValue)/Interval); varwidth=26d; varheight=169d-(MaxValue-CurrentValue)*(one_value/Interval); varx=2d; vary=169d-(169d-(MaxValue-CurrentValue)*编程客栈(one_value/Interval)); CurrentGeometry=Geometry.Parse($@"M2{y+4} a440014-4 h{width-8} a4400144 v{height-8} a44001-44 h-{width-8} a44001-4-4z"); } } }
2) 使用ThermometerExample.xaml.cs如下:
<UserControlx:Class="WPFDevelopers.Samples.ExampleViews.ThermometerExample" XMLns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers" xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews" mc:Ignorable="d" d:DesignHeight="450"d:DesignWidth="800"> <Grid> <BorderBackground="{DynamicResourceBackgroundSolidColorBrush}" CornerRadius="12" Width="400"Height="400" Effect="{StaticResourceNormalShadowDepth}"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Sliderx:Name="PART_Slider"IsSnapToTickEnabled="True" Value="10" Minimum="-10" Maximum="40" Orientation="Vertical" Height="300"/> <GridVerticalAlignment="Center" Margin="160,0,0,0"> <PathFill="{StaticResourcePrimaryMouseoverSolidColorBrush}" Stroke="{StaticResourcePrimaryMouseOverSolidColorBrush}" StrokeThickness="1"Opacity=".6" Data="{BindingElementName=PART_Thermometer,Path=CurrentGeometry,Mode=TwoWay}"/> <wpfdev:Thermometerx:Name="PART_Thermometer" CurrentValue="{BindingElementName=PART_Slider,Path=Value,Mode=TwoWay}"/> </Grid> <TextblockText="{BindingElementName=PART_Thermometer,Path=CurrentValue,StringFormat={}{0}℃}" FontSize="24"Grid.Column="1" Foreground="{StaticResourcePrimaryPressedSolidColorBrush}"FontFamily="Bahnschrift" HorizontalAlignment="Center"VerticalAlignment="Center"/> </Grid> </Border> </Grid> </UserControl>
实现效果
到此这篇关于WPF利用DrawingContext实现绘制温度计的文章就介绍到这了,更多相关WPF DrawingContext温度计内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
精彩评论