WPF利用DrawingContext實(shí)現(xiàn)繪制溫度計(jì)
WPF 使用 DrawingContext 繪制溫度計(jì)
框架使用大于等于.NET40;
Visual Studio 2022;
項(xiàng)目使用 MIT 開源許可協(xié)議;
定義Interval步長、MaxValue最大溫度值、MinValue最小溫度值。
CurrentGeometry 重新繪制當(dāng)前刻度的Path值。
CurrentValue 當(dāng)前值如果發(fā)生變化時(shí)則去重新CurrentGeometry 。
OnRender 繪制如下
RoundedRectangle溫度計(jì)的外邊框。- 使用方法
DrawText單字繪制華氏溫度文本Y軸變化。 - 使用方法
DrawText單字繪制攝氏溫度文本Y軸變化。 - 使用方法
DrawText繪制溫度計(jì)兩側(cè)的刻度數(shù)值。 - 使用方法
DrawLine繪制溫度計(jì)兩側(cè)的刻度線。

實(shí)現(xiàn)代碼
1) 準(zhǔn)備Thermometer.cs如下:
using?System;
using?System.Windows;
using?System.Windows.Controls;
using?System.Windows.Media;
namespace?WPFDevelopers.Controls
{
????public?class?Thermometer?:?Control
????{
????????public?static?readonly?DependencyProperty?MaxValueProperty?=
????????????DependencyProperty.Register("MaxValue",?typeof(double),?typeof(Thermometer),?new?UIPropertyMetadata(40.0));
????????public?static?readonly?DependencyProperty?MinValueProperty?=
????????????DependencyProperty.Register("MinValue",?typeof(double),?typeof(Thermometer),?new?UIPropertyMetadata(-10.0));
????????///?<summary>
????????///?????當(dāng)前值
????????///?</summary>
????????public?static?readonly?DependencyProperty?CurrentValueProperty?=
????????????DependencyProperty.Register("CurrentValue",?typeof(double),?typeof(Thermometer),
????????????????new?UIPropertyMetadata(OnCurrentValueChanged));
????????///?<summary>
????????///?????步長
????????///?</summary>
????????public?static?readonly?DependencyProperty?IntervalProperty?=
????????????DependencyProperty.Register("Interval",?typeof(double),?typeof(Thermometer),?new?UIPropertyMetadata(10.0));
????????///?<summary>
????????///?????當(dāng)前值的圖形坐標(biāo)點(diǎn)
????????///?</summary>
????????public?static?readonly?DependencyProperty?CurrentGeometryProperty?=
????????????DependencyProperty.Register("CurrentGeometry",?typeof(Geometry),?typeof(Thermometer),?new?PropertyMetadata(
????????????????Geometry.Parse(@"M?2?132.8
??????????????????????????????a?4?4?0?0?1?4?-4
??????????????????????????????h?18
??????????????????????????????a?4?4?0?0?1?4?4
??????????????????????????????v?32.2
??????????????????????????????a?4?4?0?0?1?-4?4
??????????????????????????????h?-18
??????????????????????????????a?4?4?0?0?1?-4?-4?z")));
????????///?<summary>
????????///?????構(gòu)造函數(shù)
????????///?</summary>
????????static?Thermometer()
????????{
????????????DefaultStyleKeyProperty.OverrideMetadata(typeof(Thermometer),
????????????????new?FrameworkPropertyMetadata(typeof(Thermometer)));
????????}
????????public?double?MaxValue
????????{
????????????get?=>?(double)GetValue(MaxValueProperty);
????????????set?=>?SetValue(MaxValueProperty,?value);
????????}
????????public?double?MinValue
????????{
????????????get?=>?(double)GetValue(MinValueProperty);
????????????set?=>?SetValue(MinValueProperty,?value);
????????}
????????public?double?CurrentValue
????????{
????????????get?=>?(double)GetValue(CurrentValueProperty);
????????????set
????????????{
????????????????SetValue(CurrentValueProperty,?value);
????????????????PaintPath();
????????????}
????????}
????????public?double?Interval
????????{
????????????get?=>?(double)GetValue(IntervalProperty);
????????????set?=>?SetValue(IntervalProperty,?value);
????????}
????????public?Geometry?CurrentGeometry
????????{
????????????get?=>?(Geometry)GetValue(CurrentGeometryProperty);
????????????set?=>?SetValue(CurrentGeometryProperty,?value);
????????}
????????private?static?void?OnCurrentValueChanged(DependencyObject?d,?DependencyPropertyChangedEventArgs?e)
????????{
????????????var?thermometer?=?d?as?Thermometer;
????????????thermometer.CurrentValue?=?Convert.ToDouble(e.NewValue);
????????}
????????public?override?void?OnApplyTemplate()
????????{
????????????base.OnApplyTemplate();
????????????PaintPath();
????????}
????????protected?override?void?OnRender(DrawingContext?drawingContext)
????????{
????????????var?brush?=?new?SolidColorBrush((Color)ColorConverter.ConvertFromString("#82848A"));
????????????var?rect?=?new?Rect();
????????????rect.Width?=?30;
????????????rect.Height?=?169;
????????????drawingContext.DrawRoundedRectangle(Brushes.Transparent,
????????????????new?Pen(brush,?2d),
????????????????rect,?8d,?8d);
????????????#region?華氏溫度
????????????drawingContext.DrawText(
????????????????DrawingContextHelper.GetFormattedText("華",
????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?textSize:?14D),
????????????????new?Point(-49,?115));
????????????drawingContext.DrawText(
????????????????DrawingContextHelper.GetFormattedText("氏",
????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?textSize:?14D),
????????????????new?Point(-49,?115?+?14));
????????????drawingContext.DrawText(
????????????????DrawingContextHelper.GetFormattedText("溫",
????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?textSize:?14D),
????????????????new?Point(-49,?115?+?28));
????????????drawingContext.DrawText(
????????????????DrawingContextHelper.GetFormattedText("度",
????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?textSize:?14D),
????????????????new?Point(-49,?115?+?42));
????????????#endregion
????????????#region?攝氏溫度
????????????drawingContext.DrawText(
????????????????DrawingContextHelper.GetFormattedText("攝",
????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?FlowDirection.LeftToRight,
????????????????????14D),?new?Point(75,?115));
????????????drawingContext.DrawText(
????????????????DrawingContextHelper.GetFormattedText("氏",
????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?FlowDirection.LeftToRight,
????????????????????14D),?new?Point(75,?115?+?14));
????????????drawingContext.DrawText(
????????????????DrawingContextHelper.GetFormattedText("溫",
????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?FlowDirection.LeftToRight,
????????????????????14D),?new?Point(75,?115?+?28));
????????????drawingContext.DrawText(
????????????????DrawingContextHelper.GetFormattedText("度",
????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?FlowDirection.LeftToRight,
????????????????????14D),?new?Point(75,?115?+?42));
????????????#endregion
????????????#region?畫刻度
????????????var?total_Value?=?MaxValue?-?MinValue;
????????????var?cnt?=?total_Value?/?Interval;
????????????var?one_value?=?161d?/?cnt;
????????????for?(var?i?=?0;?i?<=?cnt;?i++)
????????????{
????????????????var?formattedText?=?DrawingContextHelper.GetFormattedText($"{MaxValue?-?i?*?Interval}",
????????????????????(Brush)DrawingContextHelper.BrushConverter.ConvertFromString("#82848A"),?FlowDirection.LeftToRight,
????????????????????14D);
????????????????drawingContext.DrawText(formattedText,
????????????????????new?Point(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,?new?Point(-13,?i?*?one_value?-?formattedText.Height?/?2d));
????????????????if?(i?!=?0?&&?i?!=?5)
????????????????{
????????????????????drawingContext.DrawLine(new?Pen(Brushes.Black,?1d),
????????????????????????new?Point(4,?i?*?one_value),?new?Point(6,?i?*?one_value));
????????????????????drawingContext.DrawLine(new?Pen(Brushes.Black,?1d),
????????????????????????new?Point(24,?i?*?one_value),?new?Point(26,?i?*?one_value));
????????????????}
????????????}
????????????#endregion
????????}
????????///?<summary>
????????///?????動態(tài)計(jì)算當(dāng)前值圖形坐標(biāo)點(diǎn)
????????///?</summary>
????????private?void?PaintPath()
????????{
????????????var?one_value?=?161d?/?((MaxValue?-?MinValue)?/?Interval);
????????????var?width?=?26d;
????????????var?height?=?169d?-?(MaxValue?-?CurrentValue)?*?(one_value?/?Interval);
????????????var?x?=?2d;
????????????var?y?=?169d?-?(169d?-?(MaxValue?-?CurrentValue)?*?(one_value?/?Interval));
????????????CurrentGeometry?=?Geometry.Parse($@"M?2?{y?+?4}
??????????????????????????????a?4?4?0?0?1?4?-4
??????????????????????????????h?{width?-?8}
??????????????????????????????a?4?4?0?0?1?4?4
??????????????????????????????v?{height?-?8}
??????????????????????????????a?4?4?0?0?1?-4?4
??????????????????????????????h?-{width?-?8}
??????????????????????????????a?4?4?0?0?1?-4?-4?z");
????????}
????}
}
2) 使用ThermometerExample.xaml.cs如下:
<UserControl?x: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>
????????<Border?Background="{DynamicResource?BackgroundSolidColorBrush}"?
????????????????CornerRadius="12"
????????????????Width="400"?Height="400"
????????????????Effect="{StaticResource?NormalShadowDepth}">
????????????<Grid>
????????????????<Grid.ColumnDefinitions>
????????????????????<ColumnDefinition/>
????????????????????<ColumnDefinition/>
????????????????</Grid.ColumnDefinitions>
????????????????<Slider?x:Name="PART_Slider"?IsSnapToTickEnabled="True"
????????????????Value="10"
????????????????Minimum="-10"
????????????????Maximum="40"?
????????????????Orientation="Vertical"
????????????????Height="300"/>
????????????????<Grid?VerticalAlignment="Center"
??????????????????????Margin="160,0,0,0">
????????????????????<Path?Fill="{StaticResource?PrimaryMouseOverSolidColorBrush}"?
??????????????????????????Stroke="{StaticResource?PrimaryMouseOverSolidColorBrush}"
??????????????????????????StrokeThickness="1"?Opacity=".6"
??????????????????????????Data="{Binding?ElementName=PART_Thermometer,?Path=CurrentGeometry,Mode=TwoWay}"/>
????????????????????<wpfdev:Thermometer?x:Name="PART_Thermometer"
????????????????????????????????????????CurrentValue="{Binding?ElementName=PART_Slider,Path=Value,Mode=TwoWay}"/>
????????????????</Grid>
????????????????<TextBlock?Text="{Binding?ElementName=PART_Thermometer,Path=CurrentValue,StringFormat={}{0}℃}"?
???????????????????????????FontSize="24"?Grid.Column="1"
???????????????????????????Foreground="{StaticResource?PrimaryPressedSolidColorBrush}"?FontFamily="Bahnschrift"
???????????????????????????HorizontalAlignment="Center"?VerticalAlignment="Center"/>
????????????</Grid>
????????</Border>
????</Grid>
</UserControl>
實(shí)現(xiàn)效果

到此這篇關(guān)于WPF利用DrawingContext實(shí)現(xiàn)繪制溫度計(jì)的文章就介紹到這了,更多相關(guān)WPF DrawingContext溫度計(jì)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#中String StringBuilder StringBuffer類的用法
這篇文章給大家簡單介紹下C#中String StringBuilder StringBuffer三個(gè)類的用法,需要的的朋友參考下吧2017-05-05
C#中Winform窗體Form的關(guān)閉按鈕變灰色的方法
這篇文章主要介紹了C#中Winform窗體Form的關(guān)閉按鈕變灰色的方法,對于C#程序界面的設(shè)計(jì)有一定的借鑒價(jià)值,需要的朋友可以參考下2014-08-08

