当前位置: 首页 > article >正文

WPF 实现windows文件压缩文件解压过程动画

目标最终实现整体拆分分步实现1.控件的基底是一个实心的矩形2.在基底上绘制绿色网格线类似棋盘的效果3.有进度条显示进度条是长度可变的浅绿色的矩形块4.有实时速度显示速度大小转为黑色实线在基底中的高度显示5.记录每个黑色实线与浅绿色的矩形块右边缘交点这些交点连线与基底的下边缘组成的轮廓填充成深绿色注意事项一、笔者实现过程中最开始设计自定义控件时继承了ProgressBar然后发现绘制的网格线这些显示不出来继承了ProgressBar的控件的整体模板是跟随ProgressBar的后来改为继承Control。二、绘制顺序可以改变顺序决定了谁覆盖谁的问题比如把黑死速度实线放在靠前位置绘制后面绘制的曲线会遮挡住黑色实线。相关知识WPF 中的DrawingContextBrushGeometryDrawing学习博客会另外写这个进度条控件用到的主要是DrawingContext类自行了解这里以思路和代码为主。完整代码控件using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Threading; namespace WpfPasteAnimation { public class MyPasteControl : System.Windows.Controls.Control { // 进度值依赖属性 public static readonly DependencyProperty ValueProperty DependencyProperty.Register(Value, typeof(double), typeof(MyPasteControl), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender, OnValueChanged)); // 最小值 public static readonly DependencyProperty MinimumProperty DependencyProperty.Register(Minimum, typeof(double), typeof(MyPasteControl), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 最大值 public static readonly DependencyProperty MaximumProperty DependencyProperty.Register(Maximum, typeof(double), typeof(MyPasteControl), new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 速度值 public static readonly DependencyProperty SpeedProperty DependencyProperty.Register(Speed, typeof(double), typeof(MyPasteControl), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 最大速度 public static readonly DependencyProperty MaxSpeedProperty DependencyProperty.Register(MaxSpeed, typeof(double), typeof(MyPasteControl), new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 浅色填充颜色进度填充 public static readonly DependencyProperty LightFillColorProperty DependencyProperty.Register(LightFillColor, typeof(Brush), typeof(MyPasteControl), new FrameworkPropertyMetadata(new SolidColorBrush(Color.FromArgb(100, 76, 175, 80)), FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 深色曲线填充颜色 public static readonly DependencyProperty DarkCurveColorProperty DependencyProperty.Register(DarkCurveColor, typeof(Brush), typeof(MyPasteControl), new FrameworkPropertyMetadata(new SolidColorBrush(Color.FromArgb(200, 33, 150, 243)), FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 曲线颜色 public static readonly DependencyProperty CurveLineColorProperty DependencyProperty.Register(CurveLineColor, typeof(Brush), typeof(MyPasteControl), new FrameworkPropertyMetadata(Brushes.Orange, FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 曲线粗细 public static readonly DependencyProperty CurveLineThicknessProperty DependencyProperty.Register(CurveLineThickness, typeof(double), typeof(MyPasteControl), new FrameworkPropertyMetadata(2.0, FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 速度线条颜色 public static readonly DependencyProperty SpeedLineColorProperty DependencyProperty.Register(SpeedLineColor, typeof(Brush), typeof(MyPasteControl), new FrameworkPropertyMetadata(Brushes.Red, FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 速度线条粗细 public static readonly DependencyProperty SpeedLineThicknessProperty DependencyProperty.Register(SpeedLineThickness, typeof(double), typeof(MyPasteControl), new FrameworkPropertyMetadata(2.0, FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 背景色 public static readonly DependencyProperty BackgroundColorProperty DependencyProperty.Register(BackgroundColor, typeof(Brush), typeof(MyPasteControl), new FrameworkPropertyMetadata(Brushes.LightGray, FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 网格线颜色 public static readonly DependencyProperty GridLineColorProperty DependencyProperty.Register(GridLineColor, typeof(Brush), typeof(MyPasteControl), new FrameworkPropertyMetadata(Brushes.DarkGray, FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 数据点颜色 public static readonly DependencyProperty DataPointColorProperty DependencyProperty.Register(DataPointColor, typeof(Brush), typeof(MyPasteControl), new FrameworkPropertyMetadata(Brushes.Yellow, FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 数据点大小 public static readonly DependencyProperty DataPointSizeProperty DependencyProperty.Register(DataPointSize, typeof(double), typeof(MyPasteControl), new FrameworkPropertyMetadata(4.0, FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 是否显示数据点 public static readonly DependencyProperty ShowDataPointsProperty DependencyProperty.Register(ShowDataPoints, typeof(bool), typeof(MyPasteControl), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 是否显示速度线条 public static readonly DependencyProperty ShowSpeedLineProperty DependencyProperty.Register(ShowSpeedLine, typeof(bool), typeof(MyPasteControl), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 是否显示网格线 public static readonly DependencyProperty ShowGridLinesProperty DependencyProperty.Register(ShowGridLines, typeof(bool), typeof(MyPasteControl), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 是否自动记录数据点 public static readonly DependencyProperty AutoRecordDataProperty DependencyProperty.Register(AutoRecordData, typeof(bool), typeof(MyPasteControl), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender, OnPropertyChanged)); // 公共属性 public double Value { get { return (double)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } } public double Minimum { get { return (double)GetValue(MinimumProperty); } set { SetValue(MinimumProperty, value); } } public double Maximum { get { return (double)GetValue(MaximumProperty); } set { SetValue(MaximumProperty, value); } } public double Speed { get { return (double)GetValue(SpeedProperty); } set { SetValue(SpeedProperty, value); } } public double MaxSpeed { get { return (double)GetValue(MaxSpeedProperty); } set { SetValue(MaxSpeedProperty, value); } } public Brush LightFillColor { get { return (Brush)GetValue(LightFillColorProperty); } set { SetValue(LightFillColorProperty, value); } } public Brush DarkCurveColor { get { return (Brush)GetValue(DarkCurveColorProperty); } set { SetValue(DarkCurveColorProperty, value); } } public Brush CurveLineColor { get { return (Brush)GetValue(CurveLineColorProperty); } set { SetValue(CurveLineColorProperty, value); } } public double CurveLineThickness { get { return (double)GetValue(CurveLineThicknessProperty); } set { SetValue(CurveLineThicknessProperty, value); } } public Brush SpeedLineColor { get { return (Brush)GetValue(SpeedLineColorProperty); } set { SetValue(SpeedLineColorProperty, value); } } public double SpeedLineThickness { get { return (double)GetValue(SpeedLineThicknessProperty); } set { SetValue(SpeedLineThicknessProperty, value); } } public Brush BackgroundColor { get { return (Brush)GetValue(BackgroundColorProperty); } set { SetValue(BackgroundColorProperty, value); } } public Brush GridLineColor { get { return (Brush)GetValue(GridLineColorProperty); } set { SetValue(GridLineColorProperty, value); } } public Brush DataPointColor { get { return (Brush)GetValue(DataPointColorProperty); } set { SetValue(DataPointColorProperty, value); } } public double DataPointSize { get { return (double)GetValue(DataPointSizeProperty); } set { SetValue(DataPointSizeProperty, value); } } public bool ShowDataPoints { get { return (bool)GetValue(ShowDataPointsProperty); } set { SetValue(ShowDataPointsProperty, value); } } public bool ShowSpeedLine { get { return (bool)GetValue(ShowSpeedLineProperty); } set { SetValue(ShowSpeedLineProperty, value); } } public bool ShowGridLines { get { return (bool)GetValue(ShowGridLinesProperty); } set { SetValue(ShowGridLinesProperty, value); } } public bool AutoRecordData { get { return (bool)GetValue(AutoRecordDataProperty); } set { SetValue(AutoRecordDataProperty, value); } } // 存储所有历史数据点永久保存不会消失 private ListDataPoint permanentHistoryPoints new ListDataPoint(); private DispatcherTimer dataCollectionTimer; private double lastRecordedProgress -1; private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control d as MyPasteControl; control?.InvalidateVisual(); } private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control d as MyPasteControl; double newValue (double)e.NewValue; double min control.Minimum; double max control.Maximum; if (newValue min) control.Value min; if (newValue max) control.Value max; control?.AddDataPoint(); control?.InvalidateVisual(); } public MyPasteControl() { this.Background Brushes.Transparent; // 启动数据收集 StartDataCollection(); } private void StartDataCollection() { dataCollectionTimer new DispatcherTimer(); dataCollectionTimer.Interval TimeSpan.FromMilliseconds(50); dataCollectionTimer.Tick (s, e) { if (AutoRecordData) { AddDataPoint(); } }; dataCollectionTimer.Start(); } private void AddDataPoint() { // 检查是否有变化避免重复记录相同的点 if (Math.Abs(lastRecordedProgress - Value) 0.01 permanentHistoryPoints.Count 0 Math.Abs(permanentHistoryPoints[permanentHistoryPoints.Count - 1].Speed - Speed) 0.01) { return; } // 添加当前数据点永久保存 permanentHistoryPoints.Add(new DataPoint { Progress Value, Speed Speed, Timestamp DateTime.Now }); lastRecordedProgress Value; // 不限制数量永久保存所有点 InvalidateVisual(); } // 清空历史数据 public void ClearHistory() { permanentHistoryPoints.Clear(); lastRecordedProgress -1; InvalidateVisual(); } // 获取历史数据点数量 public int GetHistoryPointCount() { return permanentHistoryPoints.Count; } protected override void OnRender(DrawingContext drawingContext) { if (ActualWidth 0 || ActualHeight 0) return; // 绘制背景 DrawBackground(drawingContext); // 绘制浅色进度填充 DrawLightFill(drawingContext); // 绘制网格线 if (ShowGridLines) { DrawGridLines(drawingContext); } // 绘制曲线线条 DrawCurveLine(drawingContext); // 绘制曲线填充区域深色 DrawCurveFill(drawingContext); // 绘制数据点 if (ShowDataPoints) { DrawDataPoints(drawingContext); } // 绘制速度水平线 if (ShowSpeedLine) { DrawSpeedLine(drawingContext); } // 绘制边框 DrawBorder(drawingContext); // 绘制信息文本 DrawInfoText(drawingContext); } private void DrawBackground(DrawingContext drawingContext) { Rect backgroundRect new Rect(0, 0, ActualWidth, ActualHeight); drawingContext.DrawRectangle(BackgroundColor, null, backgroundRect); } private void DrawLightFill(DrawingContext drawingContext) { // 计算进度填充宽度 double percentage (Value - Minimum) / (Maximum - Minimum); percentage Math.Max(0, Math.Min(1, percentage)); double fillWidth ActualWidth * percentage; if (fillWidth 0) return; // 绘制浅色填充区域 Rect fillRect new Rect(0, 0, fillWidth, ActualHeight); drawingContext.DrawRectangle(LightFillColor, null, fillRect); } private void DrawCurveFill(DrawingContext drawingContext) { if (permanentHistoryPoints.Count 2) return; // 创建曲线填充路径几何图形 StreamGeometry curveFillGeometry new StreamGeometry(); using (StreamGeometryContext ctx curveFillGeometry.Open()) { PointCollection points new PointCollection(); // 收集所有有效的曲线点 for (int i 0; i permanentHistoryPoints.Count; i) { var point GetCurvePoint(permanentHistoryPoints[i]); if (point.HasValue) { points.Add(point.Value); } } if (points.Count 2) return; // 开始绘制路径 ctx.BeginFigure(points[0], true, true); // 添加曲线上的点 for (int i 1; i points.Count; i) { ctx.LineTo(points[i], true, false); } // 添加到底部边界点 Point bottomRight new Point(points[points.Count - 1].X, ActualHeight); Point bottomLeft new Point(points[0].X, ActualHeight); ctx.LineTo(bottomRight, true, false); ctx.LineTo(bottomLeft, true, false); } curveFillGeometry.Freeze(); // 绘制深色填充 drawingContext.DrawGeometry(DarkCurveColor, null, curveFillGeometry); } private void DrawCurveLine(DrawingContext drawingContext) { if (permanentHistoryPoints.Count 2) return; // 创建曲线路径几何图形 StreamGeometry curveLineGeometry new StreamGeometry(); using (StreamGeometryContext ctx curveLineGeometry.Open()) { bool isFirst true; for (int i 0; i permanentHistoryPoints.Count; i) { var point GetCurvePoint(permanentHistoryPoints[i]); if (point.HasValue) { if (isFirst) { ctx.BeginFigure(point.Value, false, false); isFirst false; } else { ctx.LineTo(point.Value, true, false); } } } } curveLineGeometry.Freeze(); // 绘制曲线线条 Pen curvePen new Pen(CurveLineColor, CurveLineThickness); curvePen.Freeze(); drawingContext.DrawGeometry(null, curvePen, curveLineGeometry); } private void DrawDataPoints(DrawingContext drawingContext) { if (permanentHistoryPoints.Count 0) return; foreach (var dataPoint in permanentHistoryPoints) { var point GetCurvePoint(dataPoint); if (point.HasValue) { // 绘制数据点圆形 double radius DataPointSize / 2; Rect pointRect new Rect(point.Value.X - radius, point.Value.Y - radius, DataPointSize, DataPointSize); // 创建圆形几何图形 EllipseGeometry ellipseGeometry new EllipseGeometry(pointRect); drawingContext.DrawGeometry(DataPointColor, null, ellipseGeometry); } } } private Point? GetCurvePoint(DataPoint dataPoint) { // 计算进度对应的X坐标 double progressPercentage (dataPoint.Progress - Minimum) / (Maximum - Minimum); progressPercentage Math.Max(0, Math.Min(1, progressPercentage)); double x ActualWidth * progressPercentage; // 计算速度对应的Y坐标速度越快Y值越小 double speedPercentage dataPoint.Speed / MaxSpeed; speedPercentage Math.Max(0, Math.Min(1, speedPercentage)); double y ActualHeight * (1 - speedPercentage); // 确保点在有效范围内 if (x 0 x ActualWidth y 0 y ActualHeight) { return new Point(x, y); } return null; } private void DrawSpeedLine(DrawingContext drawingContext) { if (MaxSpeed 0) return; // 计算速度线条的Y坐标 double speedPercentage Math.Min(1.0, Speed / MaxSpeed); double lineY ActualHeight * (1 - speedPercentage); // 绘制水平线条横跨整个进度条宽度 Pen speedPen new Pen(SpeedLineColor, SpeedLineThickness); speedPen.Freeze(); Point startPoint new Point(0, lineY); Point endPoint new Point(ActualWidth, lineY); drawingContext.DrawLine(speedPen, startPoint, endPoint); // 显示速度文本 DrawSpeedText(drawingContext, lineY); } private void DrawSpeedText(DrawingContext drawingContext, double lineY) { string speedText Speed.ToString(F1) MB/s; var formattedText new FormattedText( speedText, System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), 12, Brushes.White, VisualTreeHelper.GetDpi(this).PixelsPerDip); // 文本位置右侧 double textX ActualWidth - formattedText.Width - 10; double textY lineY - formattedText.Height - 5; if (textY 0) { textY lineY SpeedLineThickness 5; } // 文本背景 Rect textBackground new Rect(textX - 5, textY - 2, formattedText.Width 10, formattedText.Height 4); drawingContext.DrawRectangle(new SolidColorBrush(Color.FromArgb(200, 0, 0, 0)), null, textBackground); drawingContext.DrawText(formattedText, new Point(textX, textY)); } private void DrawGridLines(DrawingContext drawingContext) { Pen gridPen new Pen(GridLineColor, 1); gridPen.Freeze(); // 绘制垂直网格线10条 for (int i 1; i 10; i) { double x ActualWidth * i / 10; drawingContext.DrawLine(gridPen, new Point(x, 0), new Point(x, ActualHeight)); } // 绘制水平网格线5条 for (int i 1; i 5; i) { double y ActualHeight * i / 5; drawingContext.DrawLine(gridPen, new Point(0, y), new Point(ActualWidth, y)); } } private void DrawBorder(DrawingContext drawingContext) { if (BorderBrush ! null BorderThickness ! null) { Pen borderPen new Pen(BorderBrush, BorderThickness.Left); borderPen.Freeze(); Rect borderRect new Rect(0, 0, ActualWidth, ActualHeight); drawingContext.DrawRectangle(null, borderPen, borderRect); } } private void DrawInfoText(DrawingContext drawingContext) { // 显示历史数据点数量 string infoText $历史数据点: {permanentHistoryPoints.Count}; var formattedText new FormattedText( infoText, System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.FontFamily, this.FontStyle, this.FontWeight, this.FontStretch), 10, Brushes.Gray, VisualTreeHelper.GetDpi(this).PixelsPerDip); double textX 5; double textY 5; drawingContext.DrawText(formattedText, new Point(textX, textY)); } // 数据点结构 private class DataPoint { public double Progress { get; set; } public double Speed { get; set; } public DateTime Timestamp { get; set; } } } }测试主窗体Window x:ClassWpfPasteAnimation.MainWindow xmlnshttp://schemas.microsoft.com/winfx/2006/xaml/presentation xmlns:xhttp://schemas.microsoft.com/winfx/2006/xaml xmlns:dhttp://schemas.microsoft.com/expression/blend/2008 xmlns:localclr-namespace:WpfPasteAnimation xmlns:mchttp://schemas.openxmlformats.org/markup-compatibility/2006 TitleMainWindow Width800 Height450 mc:Ignorabled Grid Margin20 Grid.RowDefinitions RowDefinition HeightAuto / RowDefinition HeightAuto / RowDefinition HeightAuto / RowDefinition HeightAuto / RowDefinition HeightAuto / RowDefinition HeightAuto / /Grid.RowDefinitions !-- 永久曲线进度条 -- local:MyPasteControl x:NameCurveProgressBar Grid.Row0 Width800 Height250 Margin0,10 AutoRecordDataTrue BackgroundColor#F0F0F0 BorderBrush#666666 BorderThickness2 CurveLineColorGreen CurveLineThickness3 DarkCurveColorGreen DataPointColorGreen DataPointSize5 GridLineColorGreen LightFillColorLightGreen MaxSpeed100 Maximum100 Minimum0 ShowDataPointsFalse ShowGridLinesTrue ShowSpeedLineTrue Speed0 SpeedLineColorBlack SpeedLineThickness2 Value0 / !-- 控制面板 -- GroupBox Grid.Row1 Margin0,20 Header控制面板 StackPanel Margin10 TextBlock Margin0,5 FontWeightBold Text进度控制 / Slider x:NameProgressSlider Maximum100 Minimum0 Value0 / TextBlock Margin5 HorizontalAlignmentCenter Text{Binding ElementNameProgressSlider, PathValue, StringFormat进度{0:F0}%} / TextBlock Margin0,15,0,5 FontWeightBold Text速度控制 (MB/s) / Slider x:NameSpeedSlider Maximum100 Minimum0 Value0 / TextBlock Margin5 HorizontalAlignmentCenter Text{Binding ElementNameSpeedSlider, PathValue, StringFormat速度{0:F1} MB/s} / TextBlock Margin0,15,0,5 FontWeightBold Text最大速度 (MB/s) / Slider x:NameMaxSpeedSlider Maximum200 Minimum10 Value100 / TextBlock Margin5 HorizontalAlignmentCenter Text{Binding ElementNameMaxSpeedSlider, PathValue, StringFormat最大速度{0:F0} MB/s} / /StackPanel /GroupBox !-- 模拟按钮 -- StackPanel Grid.Row2 Margin0,10 HorizontalAlignmentCenter OrientationHorizontal Button Margin5 Padding15,8 Background#4CAF50 ClickSimulateFullDownload_Click Content模拟完整下载 ForegroundWhite / Button Margin5 Padding15,8 Background#FF9800 ClickSimulateRandom_Click Content模拟随机波动 ForegroundWhite / Button Margin5 Padding15,8 Background#2196F3 ClickAddTestPoint_Click Content添加测试点 ForegroundWhite / Button Margin5 Padding15,8 Background#F44336 ClickClearHistory_Click Content清空历史 ForegroundWhite / Button Margin5 Padding15,8 ClickExportData_Click Content导出数据 / /StackPanel !-- 曲线参数 -- GroupBox Grid.Row3 Margin0,10 Header曲线参数 StackPanel Margin10 StackPanel Margin0,5 OrientationHorizontal TextBlock Width80 VerticalAlignmentCenter Text曲线粗细 / Slider x:NameCurveThicknessSlider Width150 Maximum5 Minimum1 Value3 / TextBlock Margin10,0 VerticalAlignmentCenter Text{Binding ElementNameCurveThicknessSlider, PathValue, StringFormat{}{0:F0}} / /StackPanel StackPanel Margin0,5 OrientationHorizontal TextBlock Width80 VerticalAlignmentCenter Text数据点大小 / Slider x:NameDataPointSizeSlider Width150 Maximum10 Minimum2 Value5 / TextBlock Margin10,0 VerticalAlignmentCenter Text{Binding ElementNameDataPointSizeSlider, PathValue, StringFormat{}{0:F0}} / /StackPanel CheckBox x:NameShowDataPointsCheck Margin0,5 CheckedDataPointCheck_Changed Content显示数据点 IsCheckedTrue UncheckedDataPointCheck_Changed / CheckBox x:NameShowSpeedLineCheck Margin0,5 CheckedSpeedLineCheck_Changed Content显示速度水平线 IsCheckedTrue UncheckedSpeedLineCheck_Changed / CheckBox x:NameShowGridLinesCheck Margin0,5 CheckedGridLineCheck_Changed Content显示网格线 IsCheckedTrue UncheckedGridLineCheck_Changed / CheckBox x:NameAutoRecordCheck Margin0,5 CheckedAutoRecordCheck_Changed Content自动记录数据点 IsCheckedTrue UncheckedAutoRecordCheck_Changed / /StackPanel /GroupBox !-- 状态显示 -- TextBlock x:NameStatusText Grid.Row4 Margin0,15 HorizontalAlignmentCenter FontSize12 ForegroundGray Text就绪 / !-- 统计信息 -- Border Grid.Row5 Margin0,10 Padding10 Background#F5F5F5 CornerRadius5 StackPanel HorizontalAlignmentCenter OrientationHorizontal TextBlock x:NameStatsText FontSize11 ForegroundGray Text数据点数量: 0 / /StackPanel /Border /Grid /Window主窗体代码using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Threading; namespace WpfPasteAnimation { public partial class MainWindow : Window { private DispatcherTimer simulationTimer; private Random random new Random(); private bool isSimulating false; public MainWindow() { InitializeComponent(); // 绑定控制 ProgressSlider.ValueChanged (s, e) { if (!isSimulating) { CurveProgressBar.Value e.NewValue; } UpdateStatus(); }; SpeedSlider.ValueChanged (s, e) { if (!isSimulating) { CurveProgressBar.Speed e.NewValue; } UpdateStatus(); }; MaxSpeedSlider.ValueChanged (s, e) { CurveProgressBar.MaxSpeed e.NewValue; UpdateStatus(); }; CurveThicknessSlider.ValueChanged (s, e) { CurveProgressBar.CurveLineThickness e.NewValue; }; DataPointSizeSlider.ValueChanged (s, e) { CurveProgressBar.DataPointSize e.NewValue; }; // 定时更新统计信息 DispatcherTimer statsTimer new DispatcherTimer(); statsTimer.Interval TimeSpan.FromMilliseconds(500); statsTimer.Tick (s, e) UpdateStats(); statsTimer.Start(); } private void DataPointCheck_Changed(object sender, RoutedEventArgs e) { CurveProgressBar.ShowDataPoints ShowDataPointsCheck.IsChecked ?? true; } private void SpeedLineCheck_Changed(object sender, RoutedEventArgs e) { CurveProgressBar.ShowSpeedLine ShowSpeedLineCheck.IsChecked ?? true; } private void GridLineCheck_Changed(object sender, RoutedEventArgs e) { CurveProgressBar.ShowGridLines ShowGridLinesCheck.IsChecked ?? true; } private void AutoRecordCheck_Changed(object sender, RoutedEventArgs e) { CurveProgressBar.AutoRecordData AutoRecordCheck.IsChecked ?? true; } private void SimulateFullDownload_Click(object sender, RoutedEventArgs e) { StopSimulation(); isSimulating true; double progress 0; double baseSpeed 50; simulationTimer new DispatcherTimer(); simulationTimer.Interval TimeSpan.FromMilliseconds(100); simulationTimer.Tick (s, args) { if (progress 100) { // 进度增加 progress 0.5; CurveProgressBar.Value progress; ProgressSlider.Value progress; // 速度变化模拟下载速度波动 double speedVariation random.NextDouble() * 30 - 15; double newSpeed Math.Max(5, Math.Min(CurveProgressBar.MaxSpeed, baseSpeed speedVariation)); CurveProgressBar.Speed newSpeed; SpeedSlider.Value newSpeed; UpdateStatus($下载中... {progress:F1}% | 速度: {newSpeed:F1} MB/s | 数据点: {CurveProgressBar.GetHistoryPointCount()}); } else { StopSimulation(); UpdateStatus(下载完成); isSimulating false; } }; simulationTimer.Start(); } private void SimulateRandom_Click(object sender, RoutedEventArgs e) { StopSimulation(); isSimulating true; simulationTimer new DispatcherTimer(); simulationTimer.Interval TimeSpan.FromMilliseconds(200); simulationTimer.Tick (s, args) { // 随机进度和速度 double newProgress random.NextDouble() * 100; double newSpeed random.NextDouble() * CurveProgressBar.MaxSpeed; CurveProgressBar.Value newProgress; CurveProgressBar.Speed newSpeed; ProgressSlider.Value newProgress; SpeedSlider.Value newSpeed; UpdateStatus($随机模拟 - 进度: {newProgress:F1}% | 速度: {newSpeed:F1} MB/s | 数据点: {CurveProgressBar.GetHistoryPointCount()}); }; simulationTimer.Start(); } private void AddTestPoint_Click(object sender, RoutedEventArgs e) { // 添加测试点 double randomProgress random.NextDouble() * 100; double randomSpeed random.NextDouble() * CurveProgressBar.MaxSpeed; CurveProgressBar.Value randomProgress; CurveProgressBar.Speed randomSpeed; ProgressSlider.Value randomProgress; SpeedSlider.Value randomSpeed; UpdateStatus($添加测试点 - 进度: {randomProgress:F1}%, 速度: {randomSpeed:F1} MB/s); } private void ClearHistory_Click(object sender, RoutedEventArgs e) { CurveProgressBar.ClearHistory(); UpdateStatus(历史数据已清空); UpdateStats(); } private void ExportData_Click(object sender, RoutedEventArgs e) { // 简单导出到控制台 int pointCount CurveProgressBar.GetHistoryPointCount(); System.Diagnostics.Debug.WriteLine($导出数据点: {pointCount} 个); UpdateStatus($已导出 {pointCount} 个数据点); } private void StopSimulation() { if (simulationTimer ! null) { simulationTimer.Stop(); simulationTimer null; } } private void UpdateStatus(string message null) { if (message ! null) { StatusText.Text message; } else { int pointCount CurveProgressBar.GetHistoryPointCount(); StatusText.Text $进度: {CurveProgressBar.Value:F1}%, 速度: {CurveProgressBar.Speed:F1} MB/s, 最大速度: {CurveProgressBar.MaxSpeed:F0} MB/s, 数据点: {pointCount}; } } private void UpdateStats() { int pointCount CurveProgressBar.GetHistoryPointCount(); StatsText.Text $数据点数量: {pointCount} (永久保存不会消失); } } }

相关文章:

WPF 实现windows文件压缩文件解压过程动画

目标:最终实现:整体拆分,分步实现:1.控件的基底,是一个实心的矩形2.在基底上绘制绿色网格线,类似棋盘的效果3.有进度条显示,进度条是长度可变的浅绿色的矩形块4.有实时速度显示,速度…...

在AirSim里用Python实现LQR控制:让无人机自动跟踪预设轨迹(附完整代码)

用Python实现AirSim无人机LQR轨迹跟踪:从理论到代码落地 1. 环境准备与基础概念 在开始编写代码之前,我们需要先搭建好开发环境并理解几个核心概念。AirSim是微软开源的无人机/车辆仿真平台,基于Unreal Engine构建,提供了高度逼真…...

2026专业护眼产品深度评测:告别眼干涩疲劳,哪款才是“医用级“长效养护的选择?

屏幕时代,眼睛正在为我们的工作和生活"买单"。从早起看手机的那一刻,到深夜关灯前最后一次刷屏,多数人每天面对电子屏幕的时间早已超过10小时。干涩、疲劳、视力模糊、异物感……这些曾经只出现在中老年人身上的困扰,正…...

FPGA开发必备:手把手教你安装破解Modelsim 10.5se(附环境变量配置避坑指南)

FPGA开发实战:Modelsim仿真环境搭建与高效调试技巧 对于FPGA开发者而言,一个稳定可靠的仿真环境就像厨师的刀具一样重要。Modelsim作为业界广泛使用的仿真工具,其精确的时序仿真能力可以帮助我们在硬件烧录前发现绝大多数逻辑错误。本文将从一…...

3种方法永久解决IDM激活弹窗问题 开源工具全解析

3种方法永久解决IDM激活弹窗问题 开源工具全解析 【免费下载链接】IDM-Activation-Script IDM Activation & Trail Reset Script 项目地址: https://gitcode.com/gh_mirrors/id/IDM-Activation-Script Internet Download Manager(IDM)作为一款…...

威联通NAS安全防护全攻略:10个必做设置让你的数据固若金汤

威联通NAS安全防护全攻略:10个必做设置让你的数据固若金汤 在数字化时代,数据安全已成为个人和企业最关注的议题之一。威联通NAS作为专业级网络存储设备,凭借其强大的硬件性能和丰富的软件生态,成为许多用户存储重要数据的首选。然…...

终极指南:一键解决iPhone USB网络共享驱动问题

终极指南:一键解决iPhone USB网络共享驱动问题 【免费下载链接】Apple-Mobile-Drivers-Installer Powershell script to easily install Apple USB and Mobile Device Ethernet (USB Tethering) drivers on Windows! 项目地址: https://gitcode.com/gh_mirrors/ap…...

图的存储方式详解(邻接矩阵 + 邻接表)| 算法入门必看

在算法学习中,图是仅次于树的核心数据结构,广泛应用于路径规划、网络拓扑、社交关系等场景。而图的存储是后续图论算法(DFS、BFS、最短路等)的基础——选择合适的存储方式,能直接影响算法的时间和空间效率。 本文将详细讲解图的两种最常用存储方式:邻接矩阵和邻接表,从…...

告别兼容性烦恼,让老旧应用在现代浏览器中“无缝”运行

在数字化转型的浪潮中,企业的技术架构往往承载着历史的痕迹。当我们享受着现代浏览器带来的极速体验与丰富扩展时,一个不容忽视的挑战正悄然影响着员工的工作效率与IT运维的平静——那就是“传统浏览器支持”问题。这并非一个遥不可及的技术概念&#xf…...

Pixel Fashion Atelier部署案例:中小企业低成本GPU算力优化生成方案

Pixel Fashion Atelier部署案例:中小企业低成本GPU算力优化生成方案 1. 项目概述与核心价值 Pixel Fashion Atelier是一款专为时尚设计领域打造的AI图像生成工作站,基于Stable Diffusion和Anything-v5模型构建。与传统AI工具不同,它采用独特…...

Phi-3-mini-4k-instruct-gguf作品展:面向开发者的技术文档摘要生成样例

Phi-3-mini-4k-instruct-gguf作品展:面向开发者的技术文档摘要生成样例 1. 模型简介 Phi-3-mini-4k-instruct-gguf是微软Phi-3系列中的轻量级文本生成模型GGUF版本。这个经过优化的模型特别适合处理问答、文本改写、摘要整理和简短创作等任务。作为开发者工具&…...

1688图搜接口有复购率对于选品的你们有帮助吗

1688 图搜接口的复购率数据,对选品非常有帮助,是判断商品长期生命力与供应链稳定性的核心指标。一、复购率在图搜选品中的核心价值验证商品质量与用户粘性高复购率(B 端通常 > 20%,优秀 > 30%)直接证明商品质量稳…...

无人机飞控实战:四元数微分方程在PX4中的实现与调参技巧

无人机飞控实战:四元数微分方程在PX4中的实现与调参技巧 当无人机在复杂环境中执行高速机动时,传统欧拉角描述姿态会出现万向节锁死现象。去年调试一台行业级六旋翼时,就曾遇到俯仰角接近90时控制器突然发散的情况——这正是欧拉角奇异点的典…...

react为啥不像vue3一样做diff优化(双端diff和最长递增子序列)

React 不是不能做 LIS / 双端 Diff, 而是 React 的架构目标 不追求 DOM 最优,追求调度最优 所以它故意不做 Vue 那套极致 Diff 优化。 一、先给结论(面试直接说) React 不做极致 Diff 优化,是因为它的架构方向是&…...

开源AI翻译新范式:Pixel Language Portal镜像免配置+GPU算力适配教程

开源AI翻译新范式:Pixel Language Portal镜像免配置GPU算力适配教程 1. 产品概览:像素语言跨维传送门 Pixel Language Portal(像素语言跨维传送门)是一款基于Tencent Hunyuan-MT-7B大模型构建的创新翻译工具。与传统翻译软件不同…...

实战演练:基于快马平台与vscode codex思想,快速构建业务数据可视化仪表盘

今天想和大家分享一个实战经验:如何快速构建一个业务数据可视化仪表盘。这个需求其实挺常见的,很多公司都需要通过直观的图表来展示销售数据、用户行为等关键指标。我最近在InsCode(快马)平台上尝试了这个项目,整个过程比想象中顺利很多。 需…...

RMBG-2.0实测参数详解:batch_size=1/resize=1024/alpha_threshold=0.5设定依据

RMBG-2.0实测参数详解:batch_size1/resize1024/alpha_threshold0.5设定依据 1. 项目背景与核心价值 RMBG-2.0(BiRefNet)是目前开源领域最强大的图像抠图模型之一,它在处理复杂边缘细节方面表现出色,特别是对于毛发、…...

手把手教你配置Figma MCP:打造属于你自己的AI驱动设计组件库(以阅读题为例)

智能设计革命:用Figma MCP构建AI驱动的交互式学习组件库 当设计系统遇上生成式AI,一场关于效率与智能化的变革正在悄然发生。在Figma中构建可动态响应数据的智能组件库,已成为中高级UI/UX设计师突破传统设计边界的必备技能。本文将深入解析如…...

数据库索引原理:B+树与哈希索引的深度对决

数据库索引原理:B树与哈希索引的深度对决在数据库的世界里,索引是提升查询性能的“核武器”。如果把数据库表比作一本厚厚的书,那么索引就是书中的目录。没有目录,想要找到特定的知识点只能一页页翻找(全表扫描&#x…...

从连续到离散:用Python小例子复现Mamba SSM的零阶保持离散化(含完整代码)

从连续到离散:用Python小例子复现Mamba SSM的零阶保持离散化(含完整代码) 在深度学习领域,状态空间模型(State Space Model, SSM)因其对序列数据的强大建模能力而备受关注。Mamba作为SSM的最新演进&#x…...

带爱机出国攻略——大机箱反向升级小机箱C28?

大家好,欢迎来到机械大师频道,这不前几天有位粉丝找到我们,说是打算带着自己的爱机出国,但是奈何自己原本的主机实在太大台了,于是想在显卡和内存都不换的情况下,将其他硬件全换了,并且要求机箱…...

工控机驱动安全自查:5分钟用DriverView揪出可疑第三方驱动(附分析技巧)

工控机驱动安全自查:5分钟用DriverView揪出可疑第三方驱动(附分析技巧) 工业自动化设备的稳定运行离不开安全的驱动环境。想象一下,当你负责的生产线突然出现不明原因的停机,经过层层排查,最终发现是一个来…...

SAP Analysis for Office 2.8 SP6 升级与常见问题解决指南

1. SAP Analysis for Office 2.8 SP6升级前的准备工作 升级软件就像给房子做装修,准备工作做得好,后续问题少一半。对于SAP Analysis for Office(简称AFO)2.8 SP6版本升级,我建议先做好这三件事: 第一&…...

MTK平台录音杂音怎么来的?从AudioALSACaptureDataClientAurisysNormal的mDropPopSize说起

MTK平台录音杂音问题深度解析:从硬件初始化到算法优化的全链路解决方案 在移动设备音频开发领域,MTK平台的录音杂音问题一直是困扰开发者的典型痛点。特别是录音起始阶段出现的"爆破音"或"电流声",不仅影响用户体验&…...

YimMenu:GTA5游戏体验增强与安全防护指南

YimMenu:GTA5游戏体验增强与安全防护指南 【免费下载链接】YimMenu YimMenu, a GTA V menu protecting against a wide ranges of the public crashes and improving the overall experience. 项目地址: https://gitcode.com/GitHub_Trending/yi/YimMenu 项目…...

如何快速配置Windows三指拖动功能:ThreeFingerDragOnWindows完整指南

如何快速配置Windows三指拖动功能:ThreeFingerDragOnWindows完整指南 【免费下载链接】ThreeFingersDragOnWindows Enables macOS-style three-finger dragging functionality on Windows Precision touchpads. 项目地址: https://gitcode.com/gh_mirrors/th/Thre…...

快速原型设计:使用快马平台ai一键生成c语言银行系统项目骨架

今天想和大家分享一个快速验证技术方案的小技巧——用InsCode(快马)平台的AI生成功能快速搭建C语言项目原型。最近在准备一个银行系统的课程设计时,发现这个方式特别适合用来做前期技术验证。 为什么需要快速原型 刚开始做课程设计时,最头疼的就是花大量…...

太方便了!农村自建房设计新神器,二三维设计 + 扫码看模型

还在为农村自建房设计发愁?手绘图纸看不懂、修改慢、施工易出错?飞扬集成设计系统,专为农村自建房打造,一键实现二三维一体化设计,还能扫码查看轻量化 3D 模型,让建房更高效、更直观、更省心!一…...

STM32CubeMX项目实战:从新建工程到驱动LED,一步步教你玩转HAL库(附代码解析)

STM32CubeMX实战指南:HAL库驱动LED的底层逻辑与工程化思维 第一次打开STM32CubeMX时,那种面对密密麻麻的配置选项却不知从何下手的焦虑感,相信每位嵌入式开发者都记忆犹新。不同于传统寄存器操作的直白,HAL库和图形化配置工具带来…...

用8086和蜂鸣器DIY音乐盒:手把手教你复刻童年旋律(附完整汇编代码)

用8086和蜂鸣器DIY音乐盒:手把手教你复刻童年旋律(附完整汇编代码) 记得小时候第一次听到电子贺卡发出《生日快乐》的单调旋律时,那种机械却又神奇的"音乐"让我盯着电路板研究了半天。现在想来,那些简单的方…...