基于WPF实现视频封面查看器
作者:驚鏵
这篇文章主要为大家详细介绍了WPF如何实现视频封面查看器,文中的示例代码讲解详细,对我们学习或工作有一定帮助,感兴趣的小伙伴可以了解一下
如何实现 WPF 视频封面查看器
框架使用
.NET40
;Visual Studio 2019
;- 实现视频封面查看器
NineGridView
基于Grid
实现三
行三
列,使用两
行两
列做主封面展示视频播放(也可以做rtsp
视频流播放),还剩下五
个做候选封面区展示,当点击封面区某个封面时进行替换主封面区视频(流)播放。 - 当鼠标移动到候选封面区时,动画从上一次鼠标的位置到当前鼠标位置做移动动画。
示例代码
1)新建 NineGridView.cs
代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; namespace WPFDevelopers.Controls { public class NineGridView : Grid { private int _rows = 3; private int _columns = 3; private Dictionary<Rect, int> _dicRect = new Dictionary<Rect, int>(); private Border _border; private Storyboard _storyboard; private Rect _lastRect; private int _last; public static readonly DependencyProperty SelectBrushProperty = DependencyProperty.Register("SelectBrush", typeof(Brush), typeof(NineGridView), new PropertyMetadata(Brushes.Red)); public static readonly DependencyProperty BorderThicknessProperty = DependencyProperty.Register("BorderThickness", typeof(Thickness), typeof(NineGridView), new PropertyMetadata(new Thickness(1))); public NineGridView() { Loaded += NineGridView_Loaded; SizeChanged += NineGridView_SizeChanged; } public Brush SelectBrush { get => (Brush)GetValue(SelectBrushProperty); set => SetValue(SelectBrushProperty, value); } public Thickness BorderThickness { get => (Thickness)GetValue(BorderThicknessProperty); set => SetValue(BorderThicknessProperty, value); } private void NineGridView_SizeChanged(object sender, SizeChangedEventArgs e) { if (_border == null || _last == 0) return; var frameworkElement = InternalChildren[_last] as FrameworkElement; if (frameworkElement == null) return; _border.Width = frameworkElement.ActualWidth; _border.Height = frameworkElement.ActualHeight; var point = frameworkElement.TranslatePoint(new Point(0, 0), this); CreateStoryboard(point); } private void NineGridView_Loaded(object sender, RoutedEventArgs e) { RowDefinitions.Clear(); for (int i = 0; i < _rows; i++) { var row1 = new RowDefinition(); RowDefinitions.Add(row1); } ColumnDefinitions.Clear(); for (int i = 0; i < _columns; i++) { var col1 = new ColumnDefinition(); ColumnDefinitions.Add(col1); } UIElementCollection children = InternalChildren; int numCol = 0, numRow = 0; for (int i = 0, count = children.Count; i < count; ++i) { if (i > 6) return; UIElement child = children[i]; if (child != null) { if (i == 0) { SetRowSpan(child, 2); SetColumnSpan(child, 2); } else { var num = i - 1; var col = GetColumnSpan(children[num]); col = col == 1 ? GetColumn(children[num]) : col; if (i + 1 <= _columns) { SetColumn(child, col); SetRow(child, numRow); numRow++; } else { var row = GetRowSpan(children[0]); SetColumn(child, numCol); SetRow(child, row); numCol++; } } } } if(_border != null) Children.Remove(_border); _border = new Border { BorderThickness = BorderThickness, BorderBrush = SelectBrush, VerticalAlignment = VerticalAlignment.Top, HorizontalAlignment = HorizontalAlignment.Left }; _border.Name = "PART_Adorner"; _border.RenderTransform = new TranslateTransform(); SetRowSpan(_border, _rows); SetColumnSpan(_border, _columns); _border.Width = ActualWidth / _columns - 2; _border.Height = ActualHeight / _rows - 2; var _translateTransform = (TranslateTransform)_border.RenderTransform; _translateTransform.X = _border.Width * 2 + 4; Children.Add(_border); _last = 1; } protected override void OnPreviewMouseMove(MouseEventArgs e) { base.OnPreviewMouseMove(e); var currentPoint = e.GetPosition(this); if (_lastRect.Contains(currentPoint)) return; _dicRect.Clear(); UIElementCollection children = InternalChildren; for (int i = 0, count = children.Count; i < count; ++i) { if (i >= 6 || i == 0) continue; var child = children[i] as FrameworkElement; if (child != null) { var point = child.TranslatePoint(new Point(0, 0), this); var rect = new Rect(point.X, point.Y, child.ActualWidth, child.ActualHeight); _dicRect.Add(rect, i); } } var model = _dicRect.Keys.FirstOrDefault(x => x.Contains(currentPoint)); if (model == default) return; _dicRect.TryGetValue(model, out _last); if (_border == null) return; CreateStoryboard(new Point(model.X, model.Y)); _border.Width = model.Width; _border.Height = model.Height; _lastRect = model; } void CreateStoryboard(Point point) { var sineEase = new SineEase() { EasingMode = EasingMode.EaseOut }; if (_storyboard == null) _storyboard = new Storyboard(); else _storyboard.Children.Clear(); var animationX = new DoubleAnimation { Duration = TimeSpan.FromMilliseconds(500), To = point.X, EasingFunction = sineEase }; Storyboard.SetTargetProperty(animationX, new PropertyPath("(Border.RenderTransform).(TranslateTransform.X)")); _storyboard.Children.Add(animationX); var animationY = new DoubleAnimation { Duration = TimeSpan.FromMilliseconds(500), To = point.Y, EasingFunction = sineEase }; Storyboard.SetTargetProperty(animationY, new PropertyPath("(Border.RenderTransform).(TranslateTransform.Y)")); _storyboard.Children.Add(animationY); _storyboard.Begin(_border); } } }
2)新建 NineGridViewExample.xaml
代码如下:
<UserControl x:Class="WPFDevelopers.Samples.ExampleViews.NineGridViewExample" 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:controls="clr-namespace:WPFDevelopers.Samples.Controls" xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <controls:CodeViewer> <wpfdev:NineGridView BorderThickness="1" SelectBrush="Red"> <wpfdev:NineGridView.Resources> <Style TargetType="TextBlock"> <Setter Property="Foreground" Value="White"/> <Setter Property="VerticalAlignment" Value="Center"/> <Setter Property="HorizontalAlignment" Value="Center"/> </Style> <Style TargetType="Border"> <Setter Property="Margin" Value="1"/> </Style> </wpfdev:NineGridView.Resources> <MediaElement x:Name="MyMediaElement" Loaded="MyMediaElement_Loaded" MediaEnded="MyMediaElement_MediaEnded"/> <Border Background="#282C34"> <wpfdev:SmallPanel> <TextBlock Text="信号源1"/> <Border Background="{DynamicResource PrimaryNormalSolidColorBrush}" VerticalAlignment="Top" HorizontalAlignment="Right" Padding="10,4" CornerRadius="3"> <TextBlock Text="HD"/> </Border> </wpfdev:SmallPanel> </Border> <Border Background="#282C34"> <TextBlock Text="无信号"/> </Border> <Border Background="#282C34"> <TextBlock Text="无信号"/> </Border> <Border Background="#282C34"> <TextBlock Text="无信号"/> </Border> <Border Background="#282C34"> <TextBlock Text="无信号"/> </Border> </wpfdev:NineGridView> <controls:CodeViewer.SourceCodes> <controls:SourceCodeModel CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/NineGridViewExample.xaml" CodeType="Xaml"/> <controls:SourceCodeModel CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/NineGridViewExample.xaml.cs" CodeType="CSharp"/> </controls:CodeViewer.SourceCodes> </controls:CodeViewer> </UserControl>
3)新建 NineGridViewExample.xaml.cs
代码如下:
using System; using System.IO; using System.Windows; using System.Windows.Controls; namespace WPFDevelopers.Samples.ExampleViews { /// <summary> /// NineGridViewExample.xaml 的交互逻辑 /// </summary> public partial class NineGridViewExample : UserControl { public NineGridViewExample() { InitializeComponent(); } private void MyMediaElement_Loaded(object sender, RoutedEventArgs e) { var path = "E:\\DCLI6K5UIAEmH9R.mp4"; if (File.Exists(path)) MyMediaElement.Source = new Uri("path"); } private void MyMediaElement_MediaEnded(object sender, RoutedEventArgs e) { MyMediaElement.Position = new TimeSpan(0); } } }
效果图
到此这篇关于基于WPF实现视频封面查看器的文章就介绍到这了,更多相关WPF视频封面查看器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!