创建WPF项目
添加必要的NuGet包
Install-Package Microsoft.WindowsAPICodePack-Shell
Install-Package TagLibSharp
using Microsoft.WindowsAPICodePack.Dialogs;
using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
namespace MediaPlayerApp
{
public partial class MainWindow : Window
{
private DispatcherTimer timelineSliderTimer;
private bool isDraggingSlider = false;
private bool isFullscreen = false;
public MainWindow()
{
InitializeComponent();
InitializeTimer();
LoadMediaTypes();
}
private void InitializeTimer()
{
timelineSliderTimer = new DispatcherTimer();
timelineSliderTimer.Interval = TimeSpan.FromMilliseconds(100);
timelineSliderTimer.Tick += TimelineSliderTimer_Tick;
}
private void LoadMediaTypes()
{
mediaTypeCombo.Items.Add("音频");
mediaTypeCombo.Items.Add("视频");
mediaTypeCombo.SelectedIndex = 0;
}
private void btnOpen_Click(object sender, RoutedEventArgs e)
{
var dialog = new CommonOpenFileDialog
{
Title = "选择媒体文件",
IsFolderPicker = false,
Multiselect = false
};
if (mediaTypeCombo.SelectedIndex == 0) // 音频
{
dialog.Filters.Add(new CommonFileDialogFilter("音频文件", "*.mp3;*.wav;*.aac;*.flac"));
}
else // 视频
{
dialog.Filters.Add(new CommonFileDialogFilter("视频文件", "*.mp4;*.avi;*.mkv;*.wmv"));
}
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
{
txtMediaPath.Text = dialog.FileName;
PlayMedia(dialog.FileName);
}
}
private void PlayMedia(string filePath)
{
if (!File.Exists(filePath))
{
MessageBox.Show("文件不存在!", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
mediaElement.Source = new Uri(filePath);
mediaElement.Play();
// 更新时间显示
UpdateTimeDisplay();
// 显示/隐藏视频控制区
if (mediaElement.NaturalVideoHeight > 0)
{
videoControls.Visibility = Visibility.Visible;
}
else
{
videoControls.Visibility = Visibility.Collapsed;
}
}
private void btnPlayPause_Click(object sender, RoutedEventArgs e)
{
if (mediaElement.CanPause)
{
if (mediaElement.CurrentState == System.Windows.Media.MediaElementState.Paused ||
mediaElement.CurrentState == System.Windows.Media.MediaElementState.Stopped)
{
mediaElement.Play();
btnPlayPause.Content = "❚❚";
}
else
{
mediaElement.Pause();
btnPlayPause.Content = "▶";
}
}
}
private void btnStop_Click(object sender, RoutedEventArgs e)
{
mediaElement.Stop();
btnPlayPause.Content = "▶";
timelineSlider.Value = 0;
txtTime.Text = "00:00:00 / 00:00:00";
}
private void timelineSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
{
if (!isDraggingSlider)
{
isDraggingSlider = true;
mediaElement.Position = TimeSpan.FromSeconds(timelineSlider.Value);
isDraggingSlider = false;
}
}
private void timelineSliderTimer_Tick(object sender, EventArgs e)
{
if (!isDraggingSlider)
{
timelineSlider.Value = mediaElement.Position.TotalSeconds;
}
}
private void TimelineSliderTimer_Tick(object sender, EventArgs e)
{
if (!isDraggingSlider && mediaElement.NaturalDuration.HasTimeSpan)
{
timelineSlider.Maximum = mediaElement.NaturalDuration.TimeSpan.TotalSeconds;
timelineSlider.Value = mediaElement.Position.TotalSeconds;
UpdateTimeDisplay();
}
}
private void UpdateTimeDisplay()
{
if (mediaElement.NaturalDuration.HasTimeSpan)
{
txtTime.Text = $"{mediaElement.Position.ToString(@"hh\:mm\:ss")} / {mediaElement.NaturalDuration.TimeSpan.ToString(@"hh\:mm\:ss")}";
}
else
{
txtTime.Text = "00:00:00 / --:--:--";
}
}
private void volumeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
{
mediaElement.Volume = volumeSlider.Value / 100;
}
private void mediaElement_MediaOpened(object sender, RoutedEventArgs e)
{
timelineSlider.Maximum = mediaElement.NaturalDuration.TimeSpan.TotalSeconds;
timelineSliderTimer.Start();
// 根据媒体类型设置默认音量
if (mediaTypeCombo.SelectedIndex == 0) // 音频
{
volumeSlider.Value = 70;
}
else // 视频
{
volumeSlider.Value = 50;
}
}
private void mediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
btnPlayPause.Content = "▶";
timelineSlider.Value = 0;
txtTime.Text = "00:00:00 / 00:00:00";
}
private void fullscreenToggle_Click(object sender, RoutedEventArgs e)
{
if (isFullscreen)
{
this.WindowState = WindowState.Normal;
this.WindowStyle = WindowStyle.SingleBorderWindow;
fullscreenToggle.Content = "全屏";
}
else
{
this.WindowState = WindowState.Maximized;
this.WindowStyle = WindowStyle.None;
fullscreenToggle.Content = "退出";
}
isFullscreen = !isFullscreen;
}
private void mediaElement_SizeChanged(object sender, SizeChangedEventArgs e)
{
// 视频大小自适应
if (mediaElement.NaturalVideoHeight > 0)
{
double aspectRatio = mediaElement.NaturalVideoWidth / (double)mediaElement.NaturalVideoHeight;
mediaElement.Width = this.ActualWidth - 20; // 减去边距
mediaElement.Height = mediaElement.Width / aspectRatio;
}
}
}
}
在项目中添加以下引用:
// 在MainWindow.xaml.cs中添加
private void AddToPlaylist_Click(object sender, RoutedEventArgs e)
{
var dialog = new CommonOpenFileDialog
{
Title = "选择媒体文件",
IsFolderPicker = false,
Multiselect = true
};
if (mediaTypeCombo.SelectedIndex == 0) // 音频
{
dialog.Filters.Add(new CommonFileDialogFilter("音频文件", "*.mp3;*.wav;*.aac;*.flac"));
}
else // 视频
{
dialog.Filters.Add(new CommonFileDialogFilter("视频文件", "*.mp4;*.avi;*.mkv;*.wmv"));
}
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
{
foreach (var file in dialog.FileNames)
{
playlist.Items.Add(file);
}
}
}
private void playlist_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (playlist.SelectedItem != null)
{
PlayMedia(playlist.SelectedItem.ToString());
}
}
// 在PlayMedia方法中添加
try
{
var file = TagLib.File.Create(filePath);
albumArt.Source = GetAlbumArt(file);
txtTitle.Text = file.Tag.Title ?? Path.GetFileNameWithoutExtension(filePath);
txtArtist.Text = file.Tag.Performers.Length > 0 ? file.Tag.Performers[0] : "未知艺术家";
}
catch
{
// 如果无法读取元数据,使用默认值
albumArt.Source = null;
txtTitle.Text = Path.GetFileNameWithoutExtension(filePath);
txtArtist.Text = "未知艺术家";
}
// 添加获取专辑封面的方法
private ImageSource GetAlbumArt(TagLib.File file)
{
if (file.Tag.Pictures.Length > 0)
{
var ms = new MemoryStream(file.Tag.Pictures[0].Data.Data);
return BitmapFrame.Create(ms);
}
return null;
}
// 在MainWindow.xaml.cs中添加
private void InitializeEqualizer()
{
// 这里需要使用音频处理库如NAudio来实现实际的均衡器效果
// 示例代码仅显示UI
}
// 在构造函数中调用
InitializeEqualizer();
// 在MainWindow.xaml.cs中添加
private void playbackSpeed_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
{
// 注意:MediaElement不支持直接改变播放速度
// 可以使用MediaElement的Rate属性(仅部分系统支持)
try
{
mediaElement.SpeedRatio = playbackSpeed.Value;
}
catch
{
MessageBox.Show("您的系统不支持播放速度调整", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
使用Visual Studio Installer Projects扩展创建安装包:
使用.NET Core的发布功能:
dotnet publish -c Release -r win-x64 --self-contained true /p:PublishSingleFile=true
这个WPF媒体播放器实现了以下功能:
可以根据需要进一步扩展功能,如:
这个项目适合作为学习WPF和多媒体开发的良好起点,同时也可以作为实际应用的基础版本。