WPF 多媒体MediaElement 的使用(一)

news2024/11/19 3:38:07

本章讲述MediaElement的简单使用:

WPF 中对于多媒体的支持非常完整,可以使用MediaElement 为应用程序添加媒体播放控件,以完成播放音频、视频功能。MediaElement 属于UIElement,同时也支持鼠标及键盘的操作。

想以交互方式停止、暂停和播放媒体,要将MediaElement 的 LoadedBehavior 属性设置为 Manual 。

界面布局设计

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="auto"/>
    </Grid.RowDefinitions>
    <Border BorderThickness="1" BorderBrush="LightBlue" MouseEnter="Border_MouseEnter" MouseLeave="Border_MouseLeave" >
        <Grid>
            <Image Source="/MediaElement_Demo;component/bgimage.png" Stretch="Fill" />
            <MediaElement x:Name="mediaElement" Margin="1" LoadedBehavior="Manual" MediaOpened="videoMedia_MediaOpened">
            </MediaElement>
            <TextBlock x:Name="pathStr" Margin="5 10" FontSize="15" FontWeight="Black" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Bottom" Foreground="White" Visibility="Collapsed"/>
        </Grid>
    </Border>
    <Grid Grid.Row="1" Margin="0 10 0 20">
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Slider x:Name="slid" Margin="0 0 0 0" Height="20" HorizontalAlignment="Stretch" VerticalAlignment="Center" IsSnapToTickEnabled="True"
IsMoveToPointEnabled="True" PreviewMouseLeftButtonUp="slid_PreviewMouseLeftButtonUp">
        </Slider>
        <TextBlock x:Name="playTime" Grid.Row="1" Margin="0 0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
        <TextBlock x:Name="totalTime" Grid.Row="1" Margin="0 0" HorizontalAlignment="Right" TextAlignment="Right" VerticalAlignment="Top"/>
        <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center">
            <Button Margin="5 0" Height="30" Width="80" Content="打 开" Click="OpenFileClick"/>
            <Button Margin="5 0" Height="30" Width="80" Content="停 止"  Click="StopPlayClick"/>
            <Button Margin="5 0" Height="30" Width="80" Content="快 退"  Click="FastBackClick"/>
            <Button x:Name="suspenBtn" Margin="10 0" Height="30" Width="80" Content="暂停"  Click="SuspendPlayClick"/>
            <Button Margin="5 0" Height="30" Width="80" Content="快 进"  Click="FastBorwardClick"/>
            <Button Margin="5 0" Height="30" Width="80" Content="速度+"  Click="SpeedAddClick"/>
            <Button Margin="5 0" Height="30" Width="80" Content="音量+"  Click="VolumeAddClick"/>
        </StackPanel>
    </Grid>
</Grid>

布局运行图

打开视频文件,选取视频文件

    private void OpenFileClick(object sender, RoutedEventArgs e)
    {
	OpenFileDialog fileDialog = new OpenFileDialog();
	fileDialog.Filter = "MP4 File|*.mp4|MP3 File|*.mp3|AVI Files|*.avi";
	fileDialog.ValidateNames = true;
	fileDialog.CheckPathExists = true;
	fileDialog.CheckFileExists = true;
	if (fileDialog.ShowDialog() == true)
	{
		this.mediaElement.Stop();
		this.suspenBtn.Content = "播 放";
		this.slid.Value = 0;
		this.playTime.Text = "00:00:00";
		this.mediaElement.Source = null;
		this.mediaElement.Position = new TimeSpan(0, 0, 0);
		this.mediaElement.Close();
		this.pathStr.Text = "视频地址:" + fileDialog.FileName;
		this.mediaElement.Source = new Uri(fileDialog.FileName, UriKind.Relative);
		this.mediaElement.ScrubbingEnabled = true;
		SuspendPlayClick(null, null);
	}
    }

需要获取视频的参数,比如播放时长等,可以使用MediaOpened事件(当完成媒体加载时发生)

    private void videoMedia_MediaOpened(object sender, RoutedEventArgs e)
    {
	this.slid.Maximum = (int)this.mediaElement.NaturalDuration.TimeSpan.TotalSeconds;
	TotalTime = this.mediaElement.NaturalDuration.TimeSpan;
	this.totalTime.Text = TotalTime.ToString(@"hh\:mm\:ss");
    }

播放/暂停

    private void SuspendPlayClick(object sender, RoutedEventArgs e)
    {
	if (this.suspenBtn.Content.ToString() == "播 放")
	{
		this.suspenBtn.Content = "暂 停";
		this.mediaElement.Play();
		speedTimer.Start();
	}
	else
	{
		this.suspenBtn.Content = "播 放";
		this.mediaElement.Pause();
		speedTimer.Stop();
	}
    }

快进

    private void FastBorwardClick(object sender, RoutedEventArgs e)
    {
	if (this.mediaElement != null)
	{
		this.mediaElement.Position = this.mediaElement.Position + TimeSpan.FromSeconds(10);
		this.slid.Value = (int)this.mediaElement.Position.TotalSeconds;
		this.playTime.Text = this.mediaElement.Position.ToString(@"hh\:mm\:ss");
	}
    }

快退

    private void FastBackClick(object sender, RoutedEventArgs e)
    {
	if (this.mediaElement != null)
	{
		this.mediaElement.Position = this.mediaElement.Position - TimeSpan.FromSeconds(10);
		this.slid.Value = (int)this.mediaElement.Position.TotalSeconds;
		this.playTime.Text = this.mediaElement.Position.ToString(@"hh\:mm\:ss");
	}
    }

停止

    private void StopPlayClick(object sender, RoutedEventArgs e)
    {
	if (this.mediaElement != null)
	{
		this.mediaElement.Stop();
		this.suspenBtn.Content = "播 放";
		this.mediaElement.Position = TimeSpan.FromTicks(1);
		this.slid.Value = 0; 
	}
    }

设置媒体的速率,默认值为1,大于1比正常播放快的速率

private void SpeedAddClick(object sender, RoutedEventArgs e)
{    
    this.mediaElement.SpeedRatio ++;
}

音量设置,在 0 与 1 之间的线性标尺上所表示的媒体音量。 默认值为 0.5

private void VolumeAddClick(object sender, RoutedEventArgs e)
{
    this.mediaElement.Volume += 0.1;
}

播放滑动条操作,点击滑块上任意区域,视频跳转到指定时间开始播放

    private void slid_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
	if (this.mediaElement != null && slid != null)
	{
		int value = (int)this.slid.Value;
		TimeSpan span = new TimeSpan(0, 0, value);
		this.mediaElement.Position = span;
		this.playTime.Text = this.mediaElement.Position.ToString(@"hh\:mm\:ss");
	}
    }

播放滑动条进度值刷新,这里用定时器实现刷新;

DispatcherTimer speedTimer = null;
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    speedTimer = new DispatcherTimer();
    speedTimer.Interval = TimeSpan.FromSeconds(1);
    speedTimer.Tick += new EventHandler(speedTimer_tick);
}

private void MainWindow_Unloaded(object sender, RoutedEventArgs e)
{
    speedTimer.Stop();
}

视频地址显示

private void Border_MouseLeave(object sender, MouseEventArgs e)
{
    this.pathStr.Visibility = Visibility.Collapsed;
}

private void Border_MouseEnter(object sender, MouseEventArgs e)
{
    this.pathStr.Visibility = Visibility.Visible;
}

额外知识点,播放视频旋转

<MediaElement >
  <MediaElement.LayoutTransform>
    <TransformGroup>
      <RotateTransform Angle="90" />
    </TransformGroup>
  </MediaElement.LayoutTransform>
</MediaElement>

好了,本章就讲述到这里吧,下一章讲述“使用media player MediaTimeline 来控制播放”

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

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

相关文章

通达信N字形态选股公式,突破前期高点发出信号

行情经历一波上涨之后回调&#xff0c;然后再次上涨&#xff0c;形态类似于字母N&#xff0c;这就是N字形态。该形态在不同的分析方法中均有描述&#xff0c;如123法则、波浪理论等&#xff0c;只是名称不同而已。 本文的N字形态选股公式&#xff0c;以突破前期波段高点发出信号…

2023年留学基金委(CSC)青年骨干教师出国研修项目解读及建议

5月4日&#xff0c;国家留学基金委&#xff08;CSC&#xff09;公布了2023年青年骨干教师出国研修项目通知&#xff0c;知识人网小编现将其选派工作流程、选派办法、申请材料及说明原文转载并加以解读、提出建议。 知识人网解读及建议 一、2023年的通知精神与往年相比&#xf…

MySQL索引、事务与存储引擎

数据库索引 是一个排序的列表&#xff0c;存储着索引值和这个值对应的物理地址&#xff0c;在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址&#xff08;类似于C语言的链表通过指针指向数据记录的内存地址&#xff09;无需对整个表进行扫描&#xff0c;而是先通…

C++图文安装教程,计算机零基础都能懂

系统&#xff1a;win11 软件&#xff1a;code blocks&#xff06;DEV-CPP 文章目录 一、Dev-Cpp安装步骤1.点击安装包2.选择我们的语言为English3.选择我同意即可4.点击next就可以&#xff0c;最后一个框除非是你之前有写过C的项目&#xff0c;想要清除&#xff0c;否则我们不用…

【Java|golang】2432. 处理用时最长的那个任务的员工

共有 n 位员工&#xff0c;每位员工都有一个从 0 到 n - 1 的唯一 id 。 给你一个二维整数数组 logs &#xff0c;其中 logs[i] [idi, leaveTimei] &#xff1a; idi 是处理第 i 个任务的员工的 id &#xff0c;且 leaveTimei 是员工完成第 i 个任务的时刻。所有 leaveTimei…

Android---启动速度优化

App 启动流程 1. 点击桌面 App 图标&#xff0c;Launcher 进程采用 Binder IPC 向 system_server 进程发起 startActivity 请求 &#xff1b; 2. system_server 进程接收到请求后&#xff0c;向 zygote 进程发送创建进程的请求&#xff1b; 3. zygote 进程 fork 出新的子进程…

KDGK-F断路器机械特性测试仪

一、产品概述 KDGK-F 断路器机械特性测试仪可用于各电压等级的真空、六氟化硫、少油、多油等电力系统高压开关的机械特性参数测试与测量。测量数据稳定&#xff0c;抗干扰性强&#xff0c;可在500KV等级及以下电站做实验&#xff0c;接线方便&#xff0c;操作简单&#xff0c;是…

TikTok选品要怎样才能选到爆品?!

对于做TikTok的商家而言&#xff0c;选品是非常重要的&#xff0c;因为一个产品爆了之后能带动其他产品的销量&#xff0c;那我们要如何有效的选品呢&#xff1f; 一、多平台选品逻辑 首先要知道一个点&#xff0c;在独立站爆的品也会在亚马逊爆&#xff0c;而TikTok已经成为一…

安卓Glide那些事情面试,一篇全部搞定

安卓Glide那些事情面试&#xff0c;一篇全部搞定 一.Glide有几级缓存&#xff1f;&#xff1f;&#xff1f;二.Gllide源码分析三.内存缓存和磁盘缓存LruCache算法四.Gllide基本使用五.Gllide高级使用:配置1.配置内存和磁盘缓存大小2.配置okhttp3.配置https认证4.使用 一.Glide有…

冲浪杂记——

华为od是指什么&#xff1f; 华为OD&#xff08;Open Developer Platform&#xff09;是华为面向全球开发者推出的开放平台&#xff0c;旨在为开发者提供丰富的技术资源和开发工具&#xff0c;支持开发者快速构建基于华为技术的应用程序、解决方案和服务。华为OD平台为开发者提…

微软新Bing全面开放BingChat,无需排队,直接用

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 好消息&#xff0c;所有人都能上手微软Bing了!微软表示&#xff0c;为了感谢大量用户的使用与反馈&#xff0c;从今天起新 Bing 不再有候补名单&#xff0c;只要使用微软账户登录 Bing&#xff0c;…

函数(1)

文章目录 目录1. 函数是什么2. 库函数3. 自定义函数4. 函数的参数4.1 实际参数&#xff08;实参&#xff09;4.2 形式参数&#xff08;形参&#xff09; 5. 函数的调用5.1 传值调用5.2 传址调用5.3 练习 附&#xff1a; 目录 函数是什么库函数自定义函数函数的参数函数的调用函…

实现北大官网首页的动态图标

逛网站的时候&#xff0c;看见有人在问如何实现北大官网的动态图标&#xff0c;因为做过类似的东西&#xff0c;所以想把这个方法整理下来。 点上去会有一个小动画的那种。 如何实现该图标的动态效果 一句话&#xff1a;用svg实现图标&#xff0c;利用stroke-dasharray和str…

Rust - 切片Slice

Slice类型 Slice数据类型没有所有权&#xff0c;slice允许我们引用集合中一段连续的元素序列而不用引用整个集合。字符串slice(string slice) 是String中 一部分值的引用。如下述代码示例&#xff0c;不是对整个String的引用而是对部分String的引用&#xff1a; fn main() {l…

虹科方案 | HK-Edgility面向未来的安全 SD-WAN

通过上期的文章&#xff0c;我们了解到虹科HK-Edgility软件系统《随时随地保护您的远程工作解决方案》的解决方案。这篇文章&#xff0c;我们将带您了解虹科系统在SD-WAN的方案简介。 一、时代背景 过去&#xff0c;企业使用专线或MPLS解决方案将其站点和办公室连接到企业数据中…

数据结构——链表(python版)

一、链表简介 链表是一种在存储单元上非连续、非顺序的存储结构。数据元素的逻辑顺序是通过链表中的指针链接次序实现。链表是由一系列的结点组成&#xff0c;结点可以在运行时动态生成。每个结点包含两部分&#xff1a;数据域与指针域。数据域存储数据元素&#xff0c;指针域…

封装server类,创建多个server服务

&#xff08;一&#xff09;封装server类 MessageHeader.hpp #ifndef _MessageHeader_hpp_ #define _MessageHeader_hpp_ #endif #pragma once enum CMD {CMD_LOGIN,CMD_LOGIN_RESULT,CMD_LOGOUT,CMD_LOGOUT_RESULT,CMD_NEW_USER_JOIN,CMD_ERROR };struct DataHeader {short …

安装RedisBloom插件

前言 安装RedisBloom模块会遇到很多坑&#xff0c;希望你不要和我一样踩的这么全&#x1f60f;。 下载RedisBloom插件 布隆过滤器插件下载地址 github.com/RedisBloom/RedisBloom/releases 在对应的Linux机器下载 wget https://github.com/RedisBloom/RedisBloom/archive/…

一文搞懂,这几种 API 的不同应用场景

API&#xff0c;即应用程序编程接口&#xff0c;为不同应用程序之间的数据和功能交互提供标准化的方法。在现代软件架构中&#xff0c;各种类型的 API 成为了构建了复杂应用系统的关键部分。而随着技术的发展&#xff0c;越来越多的 API 类型也出现了&#xff0c;例如&#xff…

Flash Jetson Linux 刷写系统报错处理

目录 报错一&#xff1a;No such file or directory: dtc解决方案 报错二&#xff1a;ERROR sshpass not found 等其他执行刷写的依赖包解决方案 结论 报错一&#xff1a;No such file or directory: ‘dtc’ 在使用 SDK Manager 刷写Jetson Linux 时&#xff0c;在完成了 Cre…