在我们的常见的软件界面设计中我们经常会设置软件的背景为SolidColorBrush或者LinerColorBrush、RadialGradientBrush 等一系列的颜色画刷为背景,有时我们也会使用ImageBrush添加图片来作为界面的背景,另外常用的还有DrawingBrush以及今天需要进行总结的VisualBrush,这些我们都是比较容易实现的,那么我们如果想将软件的界面设计成一个动画或者干脆播放一段视频作为背景,这个对于整个软件的效果又是一个巨大的提升。

首先我们来看看background属性,MSDN上的解释是:获取或设置用于填充控件Control的边框之间的区域的 Brush。它的类型是:Type: System.Windows.Media.Brush,所以我们能够使用具有Brush属性的控件或者属性来作为背景来填充它。

我们首先来看看前台样式的设计:

<Window x:Class="TestBackGroundWorker.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="clr-namespace:X.UI;assembly=X.UI"
xmlns:local="clr-namespace:TestBackGroundWorker"
Title="MainWindow" Height="681" Width="1000">
<Window.Resources>
<Style TargetType="local:BackgroundPlayer">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:BackgroundPlayer">
<MediaElement x:Name="Media" Stretch="Fill"></MediaElement>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Grid.Background>
<VisualBrush>
<VisualBrush.Visual>
<local:BackgroundPlayer Source="~/Images/bg.avi"></local:BackgroundPlayer>
</VisualBrush.Visual>
</VisualBrush>
</Grid.Background>
</Grid>
</Window>

  在这里我们用到了VisualBrush这个画刷,然后再在VisualBrush的Visual中添加我们自定义的Style,这个是一个非常重要的画刷,如果我们对WPF的继承关系清楚的话,我们会发现几乎所有的控件都是从Visual这个顶级的基类继承过来的,所以几乎所有的Control都能够作为VisualBrush的Visual,所以Grid的Background属性是十分丰富的,这里我们定义了一个BackgroundPlayer的自定义控件,并且更改了其控件模板。

那么我们再重点看一下这个自定义控件的后台是如何进行定义的:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls; namespace TestBackGroundWorker
{
public class BackgroundPlayer : System.Windows.Controls.Control
{
static BackgroundPlayer()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(BackgroundPlayer), new FrameworkPropertyMetadata(typeof(BackgroundPlayer)));
} public string Source
{
get { return (string)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
} public static readonly DependencyProperty SourceProperty =
DependencyProperty.Register("Source", typeof(string), typeof(BackgroundPlayer), new FrameworkPropertyMetadata("", (a, b) =>
{
BackgroundPlayer bp = a as BackgroundPlayer;
if (bp.Player != null)
{
bp.Player.Source = new Uri(b.NewValue.ToString().Replace("~", AppDomain.CurrentDomain.BaseDirectory), UriKind.RelativeOrAbsolute);
}
})); private MediaElement _player; public MediaElement Player
{
get { return _player; }
set { _player = value; }
} public override void OnApplyTemplate()
{
Player = GetTemplateChild("Media") as MediaElement;
if (null == Player)
throw new ArgumentNullException("Media"); Player.LoadedBehavior = MediaState.Manual;
Player.MediaEnded += Player_MediaEnded;
Player.MediaOpened += Player_MediaOpened;
Player.MediaFailed += Player_MediaFailed;
Player.Loaded += Player_Loaded;
if (!string.IsNullOrEmpty(Source))
{
Player.Source = new Uri(Source.Replace("~", AppDomain.CurrentDomain.BaseDirectory), UriKind.RelativeOrAbsolute);
Player.Play();
}
base.OnApplyTemplate();
} void Player_Loaded(object sender, RoutedEventArgs e)
{
} void Player_MediaFailed(object sender, ExceptionRoutedEventArgs e)
{
} void Player_MediaOpened(object sender, RoutedEventArgs e)
{
//Player.Play();
} void Player_MediaEnded(object sender, RoutedEventArgs e)
{
Player.Position = TimeSpan.FromMilliseconds();
Player.Play();
} }
}

  这里我们的自定义控件是从System.Windows.Controls.Control这里继承过来的,我们看一下相关的代码,然后做进一步的分析。首先我们必须为当前的类添加一个默认的静态构造函数,这个是非常重要的,它会更改默认的Control的样式。

static BackgroundPlayer()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(BackgroundPlayer), new FrameworkPropertyMetadata(typeof(BackgroundPlayer)));
}

  接下来我们需要为自定义控件定义一些默认的依赖项属性,首先第一个是:Source属性,既然我们将Control的属性定义为MediaElement,那么我们一定要为这个MediaElement设置相关的属性,这里我们为这个Source属性定义了一个当属性变化时的回调函数,这个在xaml中第一次为Source属性赋值时就会触发该回调函数,所以我们经常可以利用该回调函数来做一些操作,这个回调函数是非常有用的。

另外我们还需要为MediaElement设置一些常见的属性,比如说当前片源放完成后会后续进行什么操作等。

  这里我们是通过重载基类的OnApplyTemplate方法来进行相关的操作的,我们在了解WPF时必须懂得,去重载这些常见的虚方法来完成我们的操作。当然这也需要我们不断去积累。

我们来看看OnApplyTemplate这个虚方法是为了完成什么样的操作,通过重写OnApplyTemplate()后就可以通过GetTemplateChild方法获取模板里的子控件了,但是OnApplyTemplate的执行顺序有问题,当类的构造函数执行后,并不是立即执行OnApplyTemplate方法,而是延迟了一定的时间,而且如果这个自定义的控件在放到应用的项目中时如果Visibility为隐藏的话,更是不会执行OnApplyTemplate方法了,这点需要我们去留心,在我们的程序中也是通过重写OnApplyTemplate方法来获取MediaElement对象,从而为其添加事件,这是一种非常有效果的方式。

最后贴出相应的截图看看动画的效果(星空风格图)

    完整的视频是一副移动的画面,这里只是截出了很少的照片,正常播放时整个都面都动,上面的文章只是简约去分析,仅供参考。

WPF设置软件界面背景为MediaElement并播放视频的更多相关文章

  1. 保护眼睛,把常用软件的背景设置成Dark

    每天长时间使用电脑,很多软件的背景都是白色,久看对眼睛不好. 1)Google Chrome,WebDev/看新闻/看邮件/写博客.使用Stylish插件和Global Dark Style,效果相当 ...

  2. WPF 设置TextBox为空时,背景为文字提示

    WPF 设置TextBox为空时,背景为文字提示.   <TextBox FontSize="17" Height="26" Margin="2 ...

  3. WPF 后台C#设置控件背景图片

    原文:WPF 后台C#设置控件背景图片 以前的程序中有做过,当时只是记得uri很长一大段就没怎么记.今天有人问了也就写下来.   这是一个Button,设置了Background后的效果. 前台的设置 ...

  4. WPF 设置纯软件渲染

    最近看到有小伙伴说 WPF 使用硬件渲染,如何让 WPF 不使用硬件渲染,因为他觉得性能太好了.万一这个版本发布了,产品经理说下个版本要提升性能就不好了.于是就找到一个快速的方法,让程序不使用硬件渲染 ...

  5. 将android界面背景设置为黑色

    屏幕背景设置为黑色的几种方式: 新建项目时候 第二次next之后(不同sdk版本号可能不同),Background Color项点击可选. 开公布局文件,选择视图查看 就是下边二个选项卡中的第一个(G ...

  6. Wix 安装部署教程(九) --用WPF做安装界面

    经常安装PC端的应用,特别是重装系统之后,大致分为两类.一类像QQ,搜狗输入法这样的.分三步走的:第一个页面可以自定义安装路径和软件许可.第二个页面显示安装进度条,第三个页面推荐其他应用.先不管人家怎 ...

  7. C# WPF 一个设计界面

    微信公众号:Dotnet9,网站:Dotnet9,问题或建议:请网站留言, 如果对您有所帮助:欢迎赞赏. C# WPF 一个设计界面 今天正月初三,大家在家呆着挺好,不要忘了自我充电. 武汉人民加油, ...

  8. Hawk 2. 软件界面介绍

    2. 软件界面介绍 1. 基本组件 Hawk采用类似Visual Studio和Eclipse的Dock风格,所有的组件都可以悬停和切换.包括以下核心组件: 左上角区域:主要工作区,任务管理. 下方: ...

  9. 获取bing图片并自动设置为电脑桌面背景(C++完整开源程序)

    众所周知,bing搜索网站首页每日会更新一张图片,张张漂亮(额,也有一些不合我口味的),特别适合用来做电脑壁纸. 我们想要将bing网站背景图片设置为电脑桌面背景的通常做法是: 上网,搜索bing 找 ...

随机推荐

  1. P1705 爱与愁过火(背包)

    本来是个搜索题,但是自觉的成了背包! 多重用正序,01用逆序. 抽象出来一下,一个物体的体积为ai, 每次装入背包需要bi(在题目中为菜数量)分钟(这个题目只是bi为 1 而已)问在r分钟内,装比n大 ...

  2. P1217 [USACO1.5]回文质数 Prime Palindromes(技巧+暴力枚举+线性筛)

    技巧:就是偶数位的回文数字一定不是质数---------证明:奇数位之和sum1==偶数位之和sum2的数字可以被11整除.(11除外,这是一个坑点) 最高位,最低位必须是 1, 3, 7, 9 暴力 ...

  3. 【ES6】=>含义

    =>是es6语法中的arrow function (x) => x + 6 相当于 function(x){ return x + 6; }; var ids = this.sels.ma ...

  4. PHP 3 函数

    PHP 的真正力量来自它的函数:它拥有超过 1000 个内建的函数. PHP 用户定义函数 除了内建的 PHP 函数,我们可以创建我们自己的函数. 函数是可以在程序中重复使用的语句块. 页面加载时函数 ...

  5. sqlachemy 获取新创建对象的id,flush与commit

    for account_info in valid_account_detail: try: account = account_info.get('account') password = acco ...

  6. CRF 条件随机场工具包

    CRF - 条件随机场 工具包(python/c++) 项目案例 ConvCRF+FullCRF https://github.com/MarvinTeichmann/ConvCRF 需要的包Opti ...

  7. Android Studio 2.2新增布局——ConstraintLayout完全解析

    ,但是Button并没有紧贴到布局的最右侧,这是为什么呢?实际上,Android Studio给控件的每个方向上的约束都默认添加了一个16dp的间距,从Inspector上面也可以明显地看出来这些间距 ...

  8. Django model中的class Meta详解

    通过一个内嵌类 "class Meta" 给你的 model 定义元数据, 类似下面这样: class Foo(models.Model): bar = models.CharFi ...

  9. HashMap是如何工作的

    目录 1 HashMap在JAVA中的怎么工作的? 2 什么是哈希? 3 HashMap 中的 Node 类 4 键值对在 HashMap 中是如何存储的 5 哈希碰撞及其处理 6 HashMap 的 ...

  10. 一起学习造轮子(三):从零开始写一个React-Redux

    本文是一起学习造轮子系列的第三篇,本篇我们将从零开始写一个React-Redux,本系列文章将会选取一些前端比较经典的轮子进行源码分析,并且从零开始逐步实现,本系列将会学习Promises/A+,Re ...