要求1:
1. 程序应能够读取MP3文件,并播放其中的音频。
2. 程序应能够处理可能出现的异常,如文件不存在、文件读取错误等。
3. 程序应具有良好的用户界面,方便用户进行操作。
4. 程序应具有良好的兼容性,能在不同版本的C#中正常运行。
提示:此功能可以使用WindowsMediaPlayer控件
要求2:
1. 程序应能够播放ogg文件。
2. 程序应能够处理可能出现的异常,如文件不存在、文件读取错误等。
3. 程序应具有良好的用户界面,方便用户进行操作。
4. 程序应具有良好的兼容性,能在不同版本的C#中正常运行。
提示:此功能可以使用Nuget程序包中的Naudi.Vorbis控件
分析:
要实现这样的程序,我们需要使用Windows Forms来创建用户界面,并使用Windows Media Player控件(对于MP3)和Naudi.Vorbis库(对于OGG)来播放音频文件。由于Windows Media Player控件不支持OGG格式,我们将使用Naudi.Vorbis库来处理OGG文件的播放。
设计:
1.歌单容器listBox控件设计
我们可以用listBox控件来实现歌曲的存放,代码如下:
private void musicplay(string filename)
{
try
{
// 设置URL属性前检查文件是否存在
if (!File.Exists(filename))
{
throw new FileNotFoundException("文件不存在。", filename);
}
// 尝试设置Windows Media Player的URL
axWindowsMediaPlayer1.URL = filename;
// 获取文件扩展名
string extension = Path.GetExtension(filename).ToLower();
// 根据文件扩展名决定播放或输出信息
switch (extension)
{
case ".ogg":
Console.WriteLine("这是.ogg文件");
// 注意:Windows Media Player可能不支持.ogg格式,需要额外的逻辑来处理这种情况
break;
case ".mp3":
// 尝试播放MP3文件
axWindowsMediaPlayer1.Ctlcontrols.play();
break;
default:
Console.WriteLine("无法识别的文件格式");
break;
}
}
catch (FileNotFoundException ex)
{
// 处理文件未找到异常
MessageBox.Show($"文件未找到:{ex.FileName}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (COMException ex) // 假设axWindowsMediaPlayer1抛出的是COMException,但具体取决于其实现
{
// 处理COM组件异常,例如Windows Media Player控件相关的问题
MessageBox.Show($"Windows Media Player发生错误:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (Exception ex) // 捕获其他所有异常
{
// 处理其他未知异常
MessageBox.Show($"发生未知错误:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
// 检查列表是否有项,以及索引是否在有效范围内
if (localmusiclist.Count > 0 && listBox1.SelectedIndex >= 0 && listBox1.SelectedIndex < localmusiclist.Count)
{
string selectedFile = localmusiclist[listBox1.SelectedIndex];
// 调用musicplay方法并传入文件路径
musicplay(selectedFile);
// 更新标签文本
label1.Text = Path.GetFileNameWithoutExtension(selectedFile);
}
else
{
// 如果没有选中项或索引无效,可以更新标签或执行其他操作
label1.Text = "未选择音乐";
}
}
catch (IndexOutOfRangeException ex)
{
// 处理索引超出范围的异常(通常不应该发生)
MessageBox.Show("索引超出范围:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (Exception ex) // 捕获musicplay方法可能抛出的所有其他异常
{
// 处理其他异常
MessageBox.Show("在播放音乐时发生错误:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
2.选择歌曲控件设计
为了将文件夹中的歌曲导入listBox控件,我们可以设计一个Button控件(我的选择歌曲控件名为buttlon1),代码如下:
private void button1_Click(object sender, EventArgs e)
{
openFileDialog1.Filter = "选择音频|*.mp3;*.flac;*.wav";
openFileDialog1.Multiselect = true;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
localmusiclist.Clear();
listBox1.Items.Clear();
if (files != null)
{
files = new string[0]; // 初始化数组
}
files = openFileDialog1.FileNames;
foreach (string fileName in files)
{
try
{
// 在尝试添加项目到ListBox或列表之前,确保文件名是有效的
listBox1.Items.Add(fileName);
localmusiclist.Add(fileName);
}
catch (Exception ex)
{
// 这里处理添加到ListBox或列表时可能发生的异常
MessageBox.Show($"在添加文件 {fileName} 到列表时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
catch (Exception ex)
{
// 这里处理在清除列表或处理文件名之前可能发生的异常(尽管这种情况不太可能)
MessageBox.Show($"在处理文件选择时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
由于OpenFileDialog
类的ShowDialog
和FileNames
属性通常是安全的,并且不太可能直接抛出异常(除非有非常特殊的情况,比如文件系统错误或权限问题),因此主要的异常处理应该放在遍历文件名并尝试将它们添加到列表和ListBox
控件中的环节。
效果展示
3.暂停控件设计
要实现一个暂停按钮button2
的功能,使得点击它时能够切换音乐的播放状态(暂停/播放),我们可以使用一个布尔变量来跟踪当前的播放状态,代码如下:
private bool isPaused = false;
private void button2_Click(object sender, EventArgs e)
{
// 检查当前的播放状态
if (isPaused)
{
// 如果音乐是暂停的,则恢复播放
axWindowsMediaPlayer1.Ctlcontrols.play();
isPaused = false; // 更新状态
}
else
{
// 如果音乐正在播放,则暂停
axWindowsMediaPlayer1.Ctlcontrols.pause();
isPaused = true; // 更新状态
}
}
在上面的代码中,isPaused
变量用来跟踪音乐当前是否处于暂停状态。当暂停键button2
被点击时,button2_Click
方法会检查这个变量的值,并相应地调用play
或pause
方法来切换音乐的播放状态。同时,isPaused
变量的值也会被更新以反映新的播放状态。
4.下一曲控件设计
为了实现歌曲顺序播放和循环播放,我们可以设计一个播放下一曲的button3,代码如下:
private void button3_Click(object sender, EventArgs e)
{
if (localmusiclist.Count > 0 && listBox1.SelectedIndex != -1)
{
// 计算下一个索引,并处理循环到最后一首的情况
int nextIndex = (listBox1.SelectedIndex + 1) % localmusiclist.Count;
// 设置URL并更新UI
axWindowsMediaPlayer1.URL = localmusiclist[nextIndex];
label1.Text = Path.GetFileNameWithoutExtension(localmusiclist[nextIndex]);
// 更新ListBox的选中项
listBox1.SelectedIndex = nextIndex;
}
else
{
// 处理没有歌曲或没有选中歌曲的情况
MessageBox.Show("没有歌曲可供选择。");
}
}
如果我们想播放ogg歌曲,可以设计一个可以播放ogg歌曲的控件button4,代码如下:
private void button4_Click(object sender, EventArgs e)
{
string oggFilePath = "";
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "播放音频|*.ogg";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
oggFilePath = openFileDialog.FileName;
try
{
// 尝试使用VorbisWaveReader打开文件
using (var vorbis = new VorbisWaveReader(oggFilePath))
{
using (var waveOut = new WaveOutEvent())
{
try
{
// 尝试初始化WaveOutEvent并播放音频
waveOut.Init(vorbis);
waveOut.Play();
// 使用waveOut.PlaybackStopped事件代替循环等待
waveOut.PlaybackStopped += (s, args) =>{};
while (waveOut.PlaybackState == PlaybackState.Playing)
{
System.Threading.Thread.Sleep(1000);
}
}
catch (Exception ex)
{
// 播放或初始化过程中出现异常
MessageBox.Show("播放或初始化音频时出错:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
catch (Exception ex)
{
// 打开文件或创建VorbisWaveReader时出现异常
MessageBox.Show("打开音频文件时出错:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
当然,我们还可以自己添加条件音量的控件:
private void trackBar1_Scroll(object sender, EventArgs e)
{
axWindowsMediaPlayer1.settings.volume = trackBar1.Value;
label2.Text = trackBar1.Value + "%";
}
几个必要的控件设计完成后,我们就可以用C#程序实现音乐文件的播放功能了,效果如下:
完整代码(其中一些方法我并没有写,但并不影响播放效果):
using NAudio;
using Un4seen.Bass;
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using NAudio.Vorbis;
using NVorbis;
using System.Runtime.InteropServices;
namespace WindowsMusic2
{
public partial class Form1 : Form
{
string[] files;
List<string> localmusiclist = new List<string> { };
public Form1()
{
InitializeComponent();
}
private void musicplay(string filename)
{
try
{
// 设置URL属性前检查文件是否存在
if (!File.Exists(filename))
{
throw new FileNotFoundException("文件不存在。", filename);
}
// 尝试设置Windows Media Player的URL
axWindowsMediaPlayer1.URL = filename;
// 获取文件扩展名
string extension = Path.GetExtension(filename).ToLower();
// 根据文件扩展名决定播放或输出信息
switch (extension)
{
case ".ogg":
Console.WriteLine("这是.ogg文件");
// 注意:Windows Media Player不支持.ogg格式,需要额外的逻辑来处理这种情况
break;
case ".mp3":
// 尝试播放MP3文件
axWindowsMediaPlayer1.Ctlcontrols.play();
break;
default:
Console.WriteLine("无法识别的文件格式");
break;
}
}
catch (FileNotFoundException ex)
{
// 处理文件未找到异常
MessageBox.Show($"文件未找到:{ex.FileName}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (COMException ex) // 假设axWindowsMediaPlayer1抛出的是COMException,但具体取决于其实现
{
// 处理COM组件异常,例如Windows Media Player控件相关的问题
MessageBox.Show($"Windows Media Player发生错误:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (Exception ex) // 捕获其他所有异常
{
// 处理其他未知异常
MessageBox.Show($"发生未知错误:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void button1_Click(object sender, EventArgs e)
{
openFileDialog1.Filter = "选择音频|*.mp3;*.flac;*.wav";
openFileDialog1.Multiselect = true;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
localmusiclist.Clear();
listBox1.Items.Clear();
if (files != null)
{
files = new string[0]; // 初始化数组
}
files = openFileDialog1.FileNames;
foreach (string fileName in files)
{
try
{
// 在尝试添加项目到ListBox或列表之前,确保文件名是有效的
listBox1.Items.Add(fileName);
localmusiclist.Add(fileName);
}
catch (Exception ex)
{
// 这里处理添加到ListBox或列表时可能发生的异常
MessageBox.Show($"在添加文件 {fileName} 到列表时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
catch (Exception ex)
{
// 这里处理在清除列表或处理文件名之前可能发生的异常(尽管这种情况不太可能)
MessageBox.Show($"在处理文件选择时出错: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
// 检查列表是否有项,以及索引是否在有效范围内
if (localmusiclist.Count > 0 && listBox1.SelectedIndex >= 0 && listBox1.SelectedIndex < localmusiclist.Count)
{
string selectedFile = localmusiclist[listBox1.SelectedIndex];
// 调用musicplay方法并传入文件路径
musicplay(selectedFile);
// 更新标签文本
label1.Text = Path.GetFileNameWithoutExtension(selectedFile);
}
else
{
// 如果没有选中项或索引无效,可以更新标签或执行其他操作
label1.Text = "未选择音乐";
}
}
catch (IndexOutOfRangeException ex)
{
// 处理索引超出范围的异常(通常不应该发生)
MessageBox.Show("索引超出范围:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (Exception ex) // 捕获musicplay方法可能抛出的所有其他异常
{
// 处理其他异常
MessageBox.Show("在播放音乐时发生错误:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void LoadFile(string path)
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
private bool isPaused = false;
private void button2_Click(object sender, EventArgs e)
{
// 检查当前的播放状态
if (isPaused)
{
// 如果音乐是暂停的,则恢复播放
axWindowsMediaPlayer1.Ctlcontrols.play();
isPaused = false; // 更新状态
}
else
{
// 如果音乐正在播放,则暂停
axWindowsMediaPlayer1.Ctlcontrols.pause();
isPaused = true; // 更新状态
}
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
axWindowsMediaPlayer1.settings.volume = trackBar1.Value;
label2.Text = trackBar1.Value + "%";
}
private void label1_Click(object sender, EventArgs e)
{
}
private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
{
}
private void button3_Click(object sender, EventArgs e)
{
if (localmusiclist.Count > 0 && listBox1.SelectedIndex != -1)
{
// 计算下一个索引,并处理循环到最后一首的情况
int nextIndex = (listBox1.SelectedIndex + 1) % localmusiclist.Count;
// 设置URL并更新UI
axWindowsMediaPlayer1.URL = localmusiclist[nextIndex];
label1.Text = Path.GetFileNameWithoutExtension(localmusiclist[nextIndex]);
// 更新ListBox的选中项
listBox1.SelectedIndex = nextIndex;
}
else
{
// 处理没有歌曲或没有选中歌曲的情况
MessageBox.Show("没有歌曲可供选择。");
}
}
private void button4_Click(object sender, EventArgs e)
{
string oggFilePath = "";
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "播放音频|*.ogg";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
oggFilePath = openFileDialog.FileName;
try
{
// 尝试使用VorbisWaveReader打开文件
using (var vorbis = new VorbisWaveReader(oggFilePath))
{
using (var waveOut = new WaveOutEvent())
{
try
{
// 尝试初始化WaveOutEvent并播放音频
waveOut.Init(vorbis);
waveOut.Play();
// 使用waveOut.PlaybackStopped事件代替循环等待
waveOut.PlaybackStopped += (s, args) =>{};
while (waveOut.PlaybackState == PlaybackState.Playing)
{
System.Threading.Thread.Sleep(1000);
}
}
catch (Exception ex)
{
// 播放或初始化过程中出现异常
MessageBox.Show("播放或初始化音频时出错:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
catch (Exception ex)
{
// 打开文件或创建VorbisWaveReader时出现异常
MessageBox.Show("打开音频文件时出错:" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
private void label2_Click(object sender, EventArgs e)
{
}
}
}
由于笔者水平有限,仅实现了作业要求的基本功能。
谢谢观看!