如何实现 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…

powershell XML数据保存为HTML

1.设置html头和尾 beginning内包含表格表头 $beginning {<html><head><meta charset"utf-8" /><title>Report</title><STYLE type"text/css">h1 {font-family:SegoeUI, sans-serif; font-size:30}th {font-family:…

浏览器自动化操作标准--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…

python3用list实现栈

工作中遇到的需求&#xff0c;****代表标签数据别的信息&#xff1a; D01  ********  1  ******** D01  ********  2  ******** D01  ********  3  ******** D01  ********  4  ******** D02  ********  1  ******** D02  ********  2  **…

powershell 脚本运行策略,参数....

1.运行策略 Powershell一般初始化情况下都会禁止脚本执行。脚本能否执行取决于Powershell的执行策略。 PS E:> Get-ExecutionPolicy Restricted PS E:> Set-ExecutionPolicy UnRestricted 2.直接运行 PS E:> "Hello,Powershell Script" > MyScript.ps…

linux每日命令(5):mkdir命令

阅读目录(Content)1&#xff0e;命令格式&#xff1a;2&#xff0e;命令功能&#xff1a;3&#xff0e;命令参数&#xff1a;4&#xff0e;命令实例&#xff1a;1&#xff1a;创建一个空目录2&#xff1a;递归创建多个目录3&#xff1a;创建权限为777的目录4&#xff1a;创建新…

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 轻量目…

powershell 查看系统设备\device status

查看设备 $allDevice"C:\Data\soundDevAll.txt" (Get-WmiObject -Class Win32_SoundDevice).Name|Out-File $allDevice device status $deviceInfoGet-WmiObject Win32_PnPEntity| select Name, Status | where {$_.Name -like "$deviceName"} $set…

Fish Shell 使用笔记

安装Fish Shell brew install fish 安装Oh My Fish curl -L https://get.oh-my.fish | fish 安装Fisher curl https://git.io/fisher --create-dirs -sLo ~/.config/fish/functions/fisher.fish 配置 autojump clone autojump git clone https://github.com/wting/autojum…

Entity Framework Core 7中高效地进行批量数据插入

因为之前的版本中&#xff0c;EF Core无法实现高效地批量插入、修改、删除数据&#xff0c;所以我开发了Zack.EFCore.Batch这个开源项目&#xff0c;比较受大家的欢迎&#xff0c;获得了400多个star。从.NET 7开始&#xff0c;微软在Entity Framework Core 7内置了对高效地批量…

Hive学习之路 (一)Hive初识

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

angularJs select绑定的model 取不到值

内容结构 一.原因分析 二. 解决办法 一.原因分析 1.由于原型继承的关系&#xff0c;修改父级对象中的someBareValue会同时修改子对象中的值&#xff0c;但反之则不行。2.ng-if 以及 ng-repeat 会创建一个子级作用域&#xff0c;如果在这俩个指令中添加了元素&a…

PS2019摄影后期处理(三)通透....

一、PS可选颜色 在对应颜色进行cmyk加减