This commit is contained in:
164
AlarmScrollingText.cs
Normal file
164
AlarmScrollingText.cs
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Animation;
|
||||||
|
using System.Windows.Threading;
|
||||||
|
|
||||||
|
namespace PLCDataMonitor
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 自定义滚动报警控件(跑马灯效果 + 闪烁)
|
||||||
|
/// </summary>
|
||||||
|
public class AlarmScrollingText : ContentControl
|
||||||
|
{
|
||||||
|
private TextBlock _textBlock;
|
||||||
|
private Border _clipBorder;
|
||||||
|
private Storyboard _scrollStoryboard;
|
||||||
|
private Storyboard _blinkStoryboard;
|
||||||
|
private double _currentOffset = 0;
|
||||||
|
private DispatcherTimer _resetTimer;
|
||||||
|
|
||||||
|
public static readonly DependencyProperty TextProperty =
|
||||||
|
DependencyProperty.Register("Text", typeof(string), typeof(AlarmScrollingText),
|
||||||
|
new FrameworkPropertyMetadata(string.Empty, OnTextChanged));
|
||||||
|
|
||||||
|
public string Text
|
||||||
|
{
|
||||||
|
get { return (string)GetValue(TextProperty); }
|
||||||
|
set { SetValue(TextProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
var control = d as AlarmScrollingText;
|
||||||
|
string newText = e.NewValue as string ?? string.Empty;
|
||||||
|
control?.OnTextChanged(newText);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AlarmScrollingText()
|
||||||
|
{
|
||||||
|
// 默认样式
|
||||||
|
DefaultStyleKey = typeof(AlarmScrollingText);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnApplyTemplate()
|
||||||
|
{
|
||||||
|
base.OnApplyTemplate();
|
||||||
|
_textBlock = GetTemplateChild("PART_TextBlock") as TextBlock;
|
||||||
|
_clipBorder = GetTemplateChild("PART_ClipBorder") as Border;
|
||||||
|
|
||||||
|
if (_textBlock != null && _clipBorder != null)
|
||||||
|
{
|
||||||
|
_textBlock.Loaded += OnTextBlockLoaded;
|
||||||
|
_textBlock.SizeChanged += OnTextBlockSizeChanged;
|
||||||
|
InitializeAnimations();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTextBlockLoaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
StartScrollingIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTextBlockSizeChanged(object sender, SizeChangedEventArgs e)
|
||||||
|
{
|
||||||
|
StartScrollingIfNeeded();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTextChanged(string newText)
|
||||||
|
{
|
||||||
|
if (_textBlock != null)
|
||||||
|
{
|
||||||
|
_textBlock.Text = newText;
|
||||||
|
StartScrollingIfNeeded();
|
||||||
|
StartBlinking(newText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitializeAnimations()
|
||||||
|
{
|
||||||
|
// 滚动动画
|
||||||
|
_scrollStoryboard = new Storyboard();
|
||||||
|
var doubleAnimation = new DoubleAnimation
|
||||||
|
{
|
||||||
|
From = 0,
|
||||||
|
To = -500, // 临时值,后面动态计算
|
||||||
|
Duration = TimeSpan.FromSeconds(8),
|
||||||
|
RepeatBehavior = RepeatBehavior.Forever
|
||||||
|
};
|
||||||
|
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)"));
|
||||||
|
_scrollStoryboard.Children.Add(doubleAnimation);
|
||||||
|
|
||||||
|
// 闪烁动画(前景色交替变化)
|
||||||
|
_blinkStoryboard = new Storyboard { RepeatBehavior = RepeatBehavior.Forever };
|
||||||
|
var colorAnimation = new ColorAnimation
|
||||||
|
{
|
||||||
|
From = Colors.Red,
|
||||||
|
To = Colors.Orange,
|
||||||
|
Duration = TimeSpan.FromSeconds(0.5),
|
||||||
|
AutoReverse = true,
|
||||||
|
RepeatBehavior = RepeatBehavior.Forever
|
||||||
|
};
|
||||||
|
Storyboard.SetTargetProperty(colorAnimation, new PropertyPath("Foreground.Color"));
|
||||||
|
_blinkStoryboard.Children.Add(colorAnimation);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartScrollingIfNeeded()
|
||||||
|
{
|
||||||
|
if (_textBlock == null || _clipBorder == null) return;
|
||||||
|
|
||||||
|
// 停止当前动画
|
||||||
|
_scrollStoryboard?.Stop(_textBlock);
|
||||||
|
_textBlock.RenderTransform = new TranslateTransform();
|
||||||
|
|
||||||
|
// 如果没有报警或报警文本为空,不启动滚动
|
||||||
|
if (string.IsNullOrWhiteSpace(Text) || Text == "无报警")
|
||||||
|
return;
|
||||||
|
|
||||||
|
// 等待布局完成后获取实际宽度
|
||||||
|
Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() =>
|
||||||
|
{
|
||||||
|
double textWidth = _textBlock.ActualWidth;
|
||||||
|
double containerWidth = _clipBorder.ActualWidth;
|
||||||
|
|
||||||
|
if (textWidth <= containerWidth)
|
||||||
|
{
|
||||||
|
// 文本不够长,不需要滚动,但保持静止
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重新设置动画的目标偏移量
|
||||||
|
double targetOffset = containerWidth - textWidth;
|
||||||
|
var animation = _scrollStoryboard.Children[0] as DoubleAnimation;
|
||||||
|
if (animation != null)
|
||||||
|
{
|
||||||
|
animation.From = 0;
|
||||||
|
animation.To = targetOffset;
|
||||||
|
animation.Duration = TimeSpan.FromSeconds(Math.Max(4, textWidth / 50.0)); // 速度自适应
|
||||||
|
}
|
||||||
|
|
||||||
|
_textBlock.RenderTransform = new TranslateTransform();
|
||||||
|
_scrollStoryboard.Begin(_textBlock, true);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void StartBlinking(string alarmText)
|
||||||
|
{
|
||||||
|
if (_textBlock == null) return;
|
||||||
|
|
||||||
|
// 停止当前闪烁
|
||||||
|
_blinkStoryboard?.Stop(_textBlock);
|
||||||
|
|
||||||
|
// 如果是无效报警或无报警,恢复正常颜色并停止闪烁
|
||||||
|
if (string.IsNullOrWhiteSpace(alarmText) || alarmText == "无报警")
|
||||||
|
{
|
||||||
|
_textBlock.Foreground = SystemColors.ControlTextBrush;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开始闪烁动画
|
||||||
|
_blinkStoryboard.Begin(_textBlock, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" ?>
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<appSettings>
|
<appSettings>
|
||||||
<!--<add key="PLC_IP" value="192.168.1.170" />-->
|
<add key="PLC_IP" value="192.168.1.170" />
|
||||||
<add key="PLC_IP" value="127.0.0.1" />
|
<!--<add key="PLC_IP" value="127.0.0.1" />-->
|
||||||
<add key="PLC_PORT" value="502" />
|
<add key="PLC_PORT" value="502" />
|
||||||
</appSettings>
|
</appSettings>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
10
App.xaml
10
App.xaml
@@ -1,9 +1,13 @@
|
|||||||
<Application x:Class="滑动摩擦测试仪.App"
|
<Application x:Class="PLCDataMonitor.App"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="clr-namespace:滑动摩擦测试仪"
|
xmlns:local="clr-namespace:PLCDataMonitor"
|
||||||
StartupUri="MainWindow.xaml">
|
StartupUri="MainWindow.xaml">
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="Themes/Generic.xaml" />
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
</Application.Resources>
|
</Application.Resources>
|
||||||
</Application>
|
</Application>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
|
||||||
namespace 滑动摩擦测试仪
|
namespace PLCDataMonitor
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interaction logic for App.xaml
|
/// Interaction logic for App.xaml
|
||||||
|
|||||||
@@ -31,12 +31,12 @@
|
|||||||
|
|
||||||
|
|
||||||
<!-- 在 ResumeButton 后添加 -->
|
<!-- 在 ResumeButton 后添加 -->
|
||||||
<TextBlock x:Name="AlarmTextBlock"
|
|
||||||
Text="无报警"
|
<local:AlarmScrollingText x:Name="AlarmScrollingCtrl"
|
||||||
FontSize="10"
|
Text="无报警"
|
||||||
Foreground="Red"
|
Background="#FFF0F0F0"
|
||||||
Margin="15,0,0,0"
|
Height="40"
|
||||||
VerticalAlignment="Center"/>
|
Margin="5"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ namespace PLCDataMonitor
|
|||||||
|
|
||||||
public void UpdateAlarms(string alarmMessage)
|
public void UpdateAlarms(string alarmMessage)
|
||||||
{
|
{
|
||||||
Dispatcher.Invoke(() => AlarmTextBlock.Text = alarmMessage);
|
|
||||||
|
Dispatcher.Invoke(() => // 更新滚动报警控件的文本
|
||||||
|
AlarmScrollingCtrl.Text = alarmMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新数据显示
|
// 更新数据显示
|
||||||
|
|||||||
31
Themes/Generic.xaml
Normal file
31
Themes/Generic.xaml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="clr-namespace:PLCDataMonitor">
|
||||||
|
|
||||||
|
<Style TargetType="{x:Type local:AlarmScrollingText}">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="{x:Type local:AlarmScrollingText}">
|
||||||
|
<Border Name="PART_ClipBorder"
|
||||||
|
Background="{TemplateBinding Background}"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
ClipToBounds="True"
|
||||||
|
Height="40">
|
||||||
|
<TextBlock Name="PART_TextBlock"
|
||||||
|
Text="{TemplateBinding Text}"
|
||||||
|
FontSize="18"
|
||||||
|
FontWeight="Bold"
|
||||||
|
Foreground="Red"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
RenderTransformOrigin="0,0.5">
|
||||||
|
<TextBlock.RenderTransform>
|
||||||
|
<TranslateTransform X="0"/>
|
||||||
|
</TextBlock.RenderTransform>
|
||||||
|
</TextBlock>
|
||||||
|
</Border>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</ResourceDictionary>
|
||||||
@@ -20,4 +20,10 @@
|
|||||||
<PackageReference Include="WinForms.DataVisualization" Version="1.10.0" />
|
<PackageReference Include="WinForms.DataVisualization" Version="1.10.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Update="AlarmScrollingText.cs">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
Reference in New Issue
Block a user