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
{
publicstaticreadonlyDependencyPropertyMaxValueProperty=
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),
newFrameworkPropertyMetadata(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)DrawingContextHelper.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(
DrawingContextHelper.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}
a4400-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温度计内容请搜索中国红客联盟以前的文章或继续浏览下面的相关文章希望大家以后多多支持中国红客联盟!