雪传说 » 日志 » 用WPF实现媒体播放器
用WPF实现媒体播放器
星辰月·雪传说 发表于 2008-07-03 15:17:10
基本的视频、音频播放
视频和音频的播放采用MediaElement类。在声明时即设定其Source属性,在一组按钮的Click事件处理函数中设定其播放、暂停与停止行为。
视频播放器及对应一组按钮(用StackPanel控制其布局)在XAML中的声明如下:
<MediaElement x:Name="myVideoElement" Source="F:\CapVideos\Test.avi" MediaOpened="Element_VideoOpened" MediaEnded="Element_VideoEnded" LoadedBehavior="Manual" UnloadedBehavior="Stop" />
<StackPanel x:Name="VideoCtrlPanel" Orientation="Horizontal" Height="24" VerticalAlignment="Bottom" Margin="0,0,0,0" HorizontalAlignment="Center">
<Button x:Name="Start" Background="#55FFFFFF"
Click="StartPreview" Content="Play" Height="30" Width="100" Cursor="Hand"/>
<Button x:Name="Stop" Background="#55FFFFFF"
Click="PausePreview" Content="Pause" Height="30" Width="100" Cursor="Hand"/>
<Button x:Name="Finish" Background="#55FFFFFF"
Click="EndPreview" Content="Stop" Height ="30" Width="100" Cursor="Hand"/>
</StackPanel>
在C#文件中只需完成Element_VideoOpened、Element_VideoEnded、StartPreview、PausePreview、EndPreview几个函数的定义,一个基本的视频播放器便可以工作了。
音频播放器同样采用MediaElement类,因为音频与视频同步播放,因此不需要再增加控制按钮。
自主选择播放文件的媒体播放器
以上完成的播放器只能播放特定的媒体文件。如果要能够让用户自主选择播放文件,首先需要增加一个列表框列出当前可选文件。在此采用了TreeView类。
当程序启动时,初始化此类,枚举出所有可选的视频文件,将文件名列出:
foreach (string s in Directory.GetFiles(VideoPath, "*.avi"))//枚举特定路径下的所有avi文件
{
TreeViewItem item = new TreeViewItem(); //创建Item
item.Header = s.Substring(s.LastIndexOf("\") + 1); //从完整路径中取出文件名
item.Tag = s;
item.FontWeight = FontWeights.Bold; //设定字体等显示属性
item.FontSize = 22;
item.Foreground = Brushes.Silver;
VideoList.Items.Add(item); //将Item添加到TreeView中
}
当列表框中被选中的条目发生变化时,重新设定媒体播放器的播放来源:
private void VideoList_SelectedItemChanged(object sender, EventArgs e)
//此函数当VideoList中被选中条目发生变化时被调用
{
TreeView tree = (TreeView)sender;
TreeViewItem temp = ((TreeViewItem)tree.SelectedItem); //获取被选中条目
if (temp == null)
return;
string s = temp.Header.ToString(); //从被选中条目中获取文件名
s = VideoPath + s; //构造完整的文件路径
System.Uri PlayVideoUri = new Uri(s); //从路径字符串构造Uri
myVideoElement.Source = PlayVideoUri; //设定视频播放器的播放来源
}
进度条、播放时间和音量调节
在MediaElement下方增加了四个元素:进度条(Slider类)、播放时间文本框(TextBlock类)、总时长文本框(TextBlock类)和音量调节拖动条(Slider类)。其中音量调节拖动条只需要在ValueChanged事件发生时更新音频播放器的音量即可,总时长文本框也只需要在媒体文件加载时取出其长度信息进行显示。进度条和播放时间框稍复杂,因为MediaElement类本身并没有在播放时间刷新时触发的事件,而且其Position属性也不支持数据绑定,思考再三只能在开始播放时手工定义一个计数器(DispatcherTimer),设定它每500ms触发一个事件,在相应的事件处理函数中取出音频文件的当前播放位置,用它来刷新进度条和时间框的值。
支持进度条拖动
由于无法将播放器的播放位置属性和进度条的值绑定,所以双向交互只能手动进行。最初如音量调节拖动条一样,在播放进度条的ValueChanged事件发生时更新媒体播放器的播放位置。但实践证明这是一个没有价值的方案,因为在用户拖动进度条滑块的过程中,用于刷新进度条位置的计数器一旦触发刷新事件(这每隔0.5s就会发生一次),进度条滑块就回到了它本该在的位置,不再听从鼠标指挥。解决方法也很简单,就是在鼠标按下时让计数器暂停。所以必须手工处理关于鼠标的一系列细化的事件。最终采用的方法如下:
|
事件 |
处理方式 |
|
PreviewMouseLeftButtonDown |
刷新计数器停止运行 |
|
PreviewMouseMove |
根据进度条滑块当前位置更新播放时间文本框中显示的时间 |
|
PreviewMouseLeftButtonUp |
根据进度条滑块当前位置更新媒体播放位置;重新启动刷新计数器 |

