[C.C++] WPF利用DrawingContext实现绘制温度计

2446 0
黑夜隐士 2022-11-10 12:56:53 | 显示全部楼层 |阅读模式
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温度计内容请搜索中国红客联盟以前的文章或继续浏览下面的相关文章希望大家以后多多支持中国红客联盟!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行