如何实现 WPF 视频封面查看器

 如何实现 WPF 视频封面查看器

控件名:NineGridView

作   者:WPFDevelopersOrg - 驚鏵

原文链接[1]:https://github.com/WPFDevelopersOrg/WPFDevelopers

  • 框架使用.NET40

  • Visual Studio 2019;

  • 实现视频封面查看器NineGridView基于Grid实现列,使用列做主封面展示视频播放(也可以做rtsp视频流播放),还剩下个做候选封面区展示,当点击封面区某个封面时进行替换主封面区视频(流)播放。

  • 当鼠标移动到候选封面区时,动画从上一次鼠标的位置到当前鼠标位置做移动动画。

909f97193694b78a4af11121c2151794.png1)新建 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);}}
}
35b69a34bc0a86fef4e9052730403b90.gif

参考资料

[1]

原文链接: https://github.com/WPFDevelopersOrg/WPFDevelopers

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/280737.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何从Internet Explorer或Edge迁移到Chrome(以及为什么要迁移)

Google’s Chrome web browser is now more widely used than Microsoft’s Internet Explorer and Edge combined. If you haven’t switched to Chrome yet, here’s why you might want to–and how to quickly switch over. Google的Chrome网络浏览器现在的使用范围比Micro…

SQL中触发器的使用

创建触发器 是特殊的存储过程&#xff0c;自动执行&#xff0c;一般不要有返回值 类型&#xff1a; 1.后触发器 &#xff08;AFTER,FOR&#xff09;先执行对应语句&#xff0c;后执行触发器中的语句 2.前触发器 并没有真正的执行触发语句&#xff08;insert&#xff0c;update…

浏览器自动化操作标准--WebDriver

WebDriver是一个浏览器远程控制协议&#xff0c;是一个既定标准&#xff0c;它本身的内容非常丰富&#xff0c;本文不可能全部介绍&#xff0c;本文仅粗略带大家了解一下WebDriver的部分内容以及一个小的实际应用。想深入了解的请参考W3C文档WebDriver. 问题背景 开发的同学都知…

versa max_如何从Mac(和Vice Versa)打开或关闭iPhone的Safari选项卡

versa maxMany of us are familiar with this scenario: you’re looking something up on our iPhone, find exactly what we’re looking for, but then have to put our phone away to attend to something else. Later, while working on your Mac, you want to continue w…

【nuxtjs 指南】解决nuxtjs本地开发跨域和防止路由与api冲突问题

目前vue很火&#xff0c;大部分开发者把vue当做框架首选&#xff0c;然而spa是对搜素引擎很不友好&#xff0c;就会想到ssr&#xff0c;在vue社区nuxtjs完美的解决了这个问题&#xff0c;目前nuxt还不算太成熟&#xff0c;当然对于新手坑比较多&#xff0c;当我们确定使用了这个…

WPF效果第二百零五篇之自定义导航控件

前面摸索了一下会简单玩耍自定义控件了;今天再次分享一下N年前想要在GIS实现的一个导航控件;来看看最终实现的效果:1、先来看看前台xaml布局:2、后台路由事件就参照上一篇快捷方式3、关键依赖属性的回调触发路由事件:4、内部Arc的MouseDown事件触发路由事件:private void Arc_M…

mac命令行将输出写入文件_如何在Linux中使用命令行将PDF文件转换为可编辑文本...

mac命令行将输出写入文件There are various reasons why you might want to convert a PDF file to editable text. Maybe you need to revise an old document and all you have is the PDF version of it. Converting PDF files in Windows is easy, but what if you’re usi…

Windows Socket和Linux Socket编程的区别

2019独角兽企业重金招聘Python工程师标准>>> 1、一些常用函数的移植 http://www.vckbase.com/document/viewdoc/?id1586 2、网络 socket相关程序从Windows移植到Linux下需要注意的: 1)头文件 Windows下winsock.h/winsock2.h Linux下sys/socket.h 错误处理&…

使用 C# 开发的现代轻量级 Windows 文本编辑器

你好&#xff0c;这里是 Dotnet 工具箱&#xff0c;定期分享 Dotnet 有趣&#xff0c;实用的工具和组件&#xff0c;希望对您有用&#xff01;Notepads 是一个具有简约设计的现代化轻量级文本编辑器&#xff0c;在 github 上开源&#xff0c;由微软大佬 Jiaqi Liu 开发。开发背…

分布式压测系列之Jmeter4.0第一季

1&#xff09;Jmeter4.0介绍 jmeter是个纯java编写的开源压测工具&#xff0c;apache旗下的开源软件&#xff0c;一开始是设计为web测试的软件&#xff0c;由于发展迅猛&#xff0c;现在可以压测许多协议比如&#xff1a;http、https、soap、ftp、database数据库、LDAP 轻量目…

Hive学习之路 (一)Hive初识

Hive 简介 什么是Hive 1、Hive 由 Facebook 实现并开源 2、是基于 Hadoop 的一个数据仓库工具 3、可以将结构化的数据映射为一张数据库表 4、并提供 HQL(Hive SQL)查询功能 5、底层数据是存储在 HDFS 上 6、Hive的本质是将 SQL 语句转换为 MapReduce 任务运行 7、使不熟悉 MapR…

os 键盘快捷键截图_如何通过键盘快捷键更有效地使用OS X虚拟桌面

os 键盘快捷键截图() We like having multiple virtual desktops on OS X, especially when we can supercharge them by combining them with a few simple keyboard shortcuts. So, on that note, here are some practical ways to use OS X’s virtual desktops like you me…

旗正规则引擎内存表出错的原因及解决方法

经常我们有一些使用者问到这个问题&#xff0c;关于内存表出错的情况&#xff0c;其实问题不复杂&#xff0c;我这给大家简单的讲一下就明白了&#xff0c;如果还有什么不明白的&#xff0c;其实也都可以问厂家杭州旗正&#xff0c;随时都有人回应的。 1 内存表 1.1 汇总 1.1.1…

Shell脚本之sed的使用

1.sed命令&#xff1b;主要作用是查找&#xff1b;新增 删除 和修改替换。 user.txt daokr#cat user.txt ID Name Sex Age 1 zhang M 19 2 wang G 20 3 cheng M 10 4 huahua M 100 查找命令&#xff1a;-n 和 p&#xff08;prin…

.NET周报【11月第4期 2022-11-30】

国内文章.NET 7 的 AOT 到底能不能扛反编译&#xff1f;https://www.cnblogs.com/huangxincheng/p/16917197.html在 B 站&#xff0c;公众号上发了一篇 AOT 的文章后&#xff0c;没想到反响还是挺大的&#xff0c;都称赞这个东西能抗反编译&#xff0c;可以让破解难度极大提高&…

HDU 5673 Robot 卡特兰数

题目链接&#xff1a; http://acm.hdu.edu.cn/showproblem.php?pid5673 题目描述&#xff1a; 一个人从原点开始向右走&#xff0c; 要求N秒后回到原点&#xff0c; 且过程中不能到负半轴&#xff0c; 人有两种操作&#xff0c; 走动或者停止&#xff0c; 问总共有多少种方案&…

删除本地账户无法登录电脑_如何从Windows的登录屏幕中删除本地用户帐户

删除本地账户无法登录电脑If you have multiple user accounts on your computer, you might find it annoying to have to click on the icon for your username each time you start up the computer. To remedy this problem, you can hide a user account with a registry …

tarjan算法详解

https://blog.csdn.net/jeryjeryjery/article/details/52829142?locationNum4&fps1 以防链接失效&#xff0c;特此转载此博&#xff0c;如有侵权请见谅 在有向图G中&#xff0c;如果两个顶点间至少存在一条路径&#xff0c;称两个顶点强连通(strongly connected)。如果有向…

Gitlab简单使用CI/CD

开篇语大概是去年就想做这个事情了&#xff0c;奈何当时卡到一个docker命令找不到的问题上&#xff0c;导致文章难产了&#xff0c;墨迹了这么久&#xff0c;终于又有空来捣鼓它了。目的我们要实现的目的是我本地不断提交代码(CI),然后服务器不断进行部署(CD)的一个简单流程。准…

免费的数字图书馆_不仅是书籍:您当地图书馆可能提供的所有免费数字资料

免费的数字图书馆You might think of libraries as old fashioned, or irrelevant in the age of the internet. You’d be wrong. 您可能会认为图书馆是老式的&#xff0c;或者与互联网时代无关。 你会错的。 Modern libraries offer books, yes, but they also provide inter…