wmplayer播放器解決重點:
1. 自動播放下一首歌曲時,播放器狀態會會切換成准備,需要time監視
2. 列表用list<>,不用鍵值對,后期列表多選和自動下一首不好調用

using AxWMPLib;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace mpvplayer
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
//跨線程
Control.CheckForIllegalCrossThreadCalls = false;
}
//聲明歌曲列表字典
List<string> slist = new List<string>();
//全局目錄,暫時沒用到
string gdir = null;
//listbox1全局記數
int i = 0;
/// <summary>
/// 播放按鈕實現功能
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
//判斷音樂庫slist有沒有音樂,沒有則結束
if (slist.Count == 0)
{
return;
}
//listbox1選中非空
if (listBox1.SelectedItem != null)
{
//判斷是否是一首歌
if (Path.GetFileName(axWindowsMediaPlayer1.URL) != listBox1.SelectedItem.ToString())
{
axWindowsMediaPlayer1.URL = slist[listBox1.SelectedIndex];
axWindowsMediaPlayer1.Ctlcontrols.play();
button1.Text = "暫停";
}
else
{
if (button1.Text == "播放")
{
axWindowsMediaPlayer1.Ctlcontrols.play();
button1.Text = "暫停";
}
else
{
axWindowsMediaPlayer1.Ctlcontrols.pause();
button1.Text = "播放";
}
}
}
}
/// <summary>
/// 選中歌曲索引改變時間,自動加載歌詞,判斷是否暫停和繼續
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
//切歌時清除歌詞內容和時間
dlrc.Clear();
slrc.Clear();
//加載新歌詞
checkBox1_CheckedChanged(this, e);
try //try防止出錯
{
if (Path.GetFileName(axWindowsMediaPlayer1.URL) == listBox1.SelectedItem.ToString())
{
button1.Text = "暫停";
}
else
{
button1.Text = "播放";
}
}
catch
{
}
}
/// <summary>
/// 添加音樂按鈕實現
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object sender, EventArgs e)
{
OpenFileDialog of = new OpenFileDialog();
of.Multiselect = true;
of.InitialDirectory = @"Z:\音樂";
gdir = of.InitialDirectory;
//多類型支持寫法,用;隔開
of.Filter = "支持的格式|*.mp3;*.wav;*.flac|mp3格式|*.mp3|wav格式|*.wav|flac格式|*.flac";
of.ShowDialog();
if (of.FileNames.Length != 0)
{
foreach (var item in of.FileNames)
{
//去重
if (!slist.Contains(item))
{
slist.Add(item);
//添加進listbox
listBox1.Items.Add(Path.GetFileName(item));
i++;
}
}
}
}
/// <summary>
/// 程序啟動時暫停自動播放,默認選擇順序播放模式
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Load(object sender, EventArgs e)
{
axWindowsMediaPlayer1.settings.autoStart = false;
radioButton3.Checked = true;
// label2.Image = Image.FromFile(@"D:\Users\yaoyue\Desktop\1.png");
}
/// <summary>
/// 列表雙擊播放
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void listBox1_DoubleClick(object sender, EventArgs e)
{
try
{
axWindowsMediaPlayer1.URL = slist[listBox1.SelectedIndex];
axWindowsMediaPlayer1.Ctlcontrols.play();
button1.Text = "暫停";
}
catch
{
}
}
/// <summary>
/// 隨機播放實現,見 ax1狀態改變事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
if (radioButton1.Checked == true)
{
}
else
{
}
}
/// <summary>
/// 單曲循環模式選中
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void radioButton2_CheckedChanged(object sender, EventArgs e)
{
if (radioButton2.Checked)
{
axWindowsMediaPlayer1.settings.setMode("loop", true);
}
}
//歌詞歌曲的list
List<double> dlrc = new List<double>();
List<string> slrc = new List<string>();
/// <summary>
/// 歌詞格式化函數
/// </summary>
public void Lrcc()
{
try
{
string lrcpath = Path.ChangeExtension(axWindowsMediaPlayer1.URL, ".lrc");
//將歌詞文件讀取為數組
string[] lrcalltext = File.ReadAllLines(lrcpath, Encoding.Default);
double zs = 0;
foreach (var item in lrcalltext)
{
//只篩選出歌詞
if (Regex.IsMatch(item, @"[0-9][0-9]:[0-9][0-9].[0-9][0-9]"))
{
// a.tostring()為字符串
Match a = Regex.Match(item, @"[0-9][0-9]:[0-9][0-9].[0-9][0-9]");
Match b = Regex.Match(item, @"[^\d.\[\]:].{0,50}");
string time = a.ToString();
//分鍾的字符形式
string minute = time.Split(new char[] { ':' })[0];
//秒的字符形式
string second = time.Split(new char[] { ':', ']' })[1];
//分鍾 轉成秒
double dm = double.Parse(minute) * 60;
//秒轉換
double ds = double.Parse(second);
//總秒數
zs = dm + ds;
dlrc.Add(zs);
//歌詞
string sb = b.ToString();
slrc.Add(sb);
}
}
}
catch
{
}
}
/// <summary>
/// 選中“顯示歌詞”事件實現
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (checkBox1.Checked==true)
{
Lrcc();
}
}
/// <summary>
/// 上一首
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
int j = 0;
//因為listbox為多選模式,所以清空所有索引,之前先轉存到index
int index = listBox1.SelectedIndex;
listBox1.SelectedIndices.Clear();
if (index > j)
{
listBox1.SelectedIndex = index - 1;
}
else if (index == j)
{
listBox1.SelectedIndex = 0;
}
//模擬播放按鈕按下
button1_Click(this, e);
}
/// <summary>
/// 下一首
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button4_Click(object sender, EventArgs e)
{
int j = slist.Count;
//清空所有索引之前先轉存到index
int index = listBox1.SelectedIndex;
listBox1.SelectedIndices.Clear();
if (index < j - 1)
{
listBox1.SelectedIndex = index + 1;
}
else if (index == j)
{
listBox1.SelectedIndex = j - 1;
}
//模擬播放按鈕按下
button1_Click(this, e);
}
/// <summary>
/// 右鍵刪除,從list后面開始順序不容易亂
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 刪除ToolStripMenuItem1_Click(object sender, EventArgs e)
{
//盛放選中索引
List<int> sort = new List<int>();
foreach (var item in listBox1.SelectedIndices)
{
sort.Add((int)item);
}
//從后面的索引開始刪除,排序
sort.Sort();
sort.Reverse();
for (int i = 0; i < sort.Count; i++)
{
listBox1.Items.RemoveAt(sort[i]);
slist.RemoveAt(sort[i]);
}
}
/// <summary>
/// 右鍵添加音樂,直接調用添加音樂的btn按鈕
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 添加ToolStripMenuItem_Click_1(object sender, EventArgs e)
{
button3_Click(this, e);
}
/// <summary>
/// 音量調節大小,label設置成圖片
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void label2_Click(object sender, EventArgs e)
{
if (label2.Tag.ToString() == "1")
{
axWindowsMediaPlayer1.settings.mute = true;
label2.Tag = "2";
// label2.Image = Image.FromFile(@"D:\Users\yaoyue\Desktop\2.png");
}
else
{
axWindowsMediaPlayer1.settings.mute = false;
label2.Tag = "1";
// label2.Image = Image.FromFile(@"D:\Users\yaoyue\Desktop\1.png");
}
}
/// <summary>
/// 列表循環---音樂播放結束時自動播放下一首
/// </summary>
public void ListPlayer()
{
try
{
int i = listBox1.SelectedIndex;
//判斷當前是否是列表最后一項
if (i < listBox1.Items.Count - 1)
{
axWindowsMediaPlayer1.URL = slist[i + 1];
//因為selectindex為多選模式,所以必須clear
listBox1.SelectedIndices.Clear();
listBox1.SelectedIndex = i + 1;
}
else //重新開始
{
listBox1.SelectedIndices.Clear();
listBox1.SelectedIndex = 0;
axWindowsMediaPlayer1.URL = slist[0];
}
}
catch
{
}
}
/// <summary>
/// 隨機播放的功能函數
/// </summary>
public void RandomPlayer()
{
Random r = new Random();
int i = r.Next(0, slist.Count);
axWindowsMediaPlayer1.URL = slist[i];
listBox1.SelectedIndices.Clear();
listBox1.SelectedIndex = i;
}
/// <summary>
/// 播放器狀態改變事件,播放模式核心實現
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void axWindowsMediaPlayer1_StatusChange(object sender, EventArgs e)
{
if (radioButton2.Checked == true)
{
//在選中事件中實現,不在此事件
return;
}
else if (radioButton1.Checked == true && axWindowsMediaPlayer1.playState == WMPLib.WMPPlayState.wmppsMediaEnded)
{
//隨機模式
RandomPlayer();
}
else
{
if (axWindowsMediaPlayer1.playState == WMPLib.WMPPlayState.wmppsMediaEnded)
{
//順序模式
ListPlayer();
}
}
}
/// <summary>
/// 修復wmplayer的不自動播放bug
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void timer2_Tick(object sender, EventArgs e)
{
//播放結束時有bug,播放器狀態進入准備狀態,而不是播放,強制播放
if (axWindowsMediaPlayer1.playState == WMPLib.WMPPlayState.wmppsReady)
{
try
{
axWindowsMediaPlayer1.Ctlcontrols.play();
}
catch
{ }
}
}
/// <summary>
/// 托盤右鍵 暫停和繼續
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 暫停ToolStripMenuItem_Click(object sender, EventArgs e)
{
if (axWindowsMediaPlayer1.playState == WMPLib.WMPPlayState.wmppsPlaying)
{
axWindowsMediaPlayer1.Ctlcontrols.pause();
contextMenuStrip2.Items[0].Text = "繼續";
}
else
{
axWindowsMediaPlayer1.Ctlcontrols.play();
contextMenuStrip2.Items[0].Text = "暫停";
}
}
/// <summary>
/// 托盤圖標雙擊暫停,繼續
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (axWindowsMediaPlayer1.playState == WMPLib.WMPPlayState.wmppsPlaying)
{
axWindowsMediaPlayer1.Ctlcontrols.pause();
}
else
{
axWindowsMediaPlayer1.Ctlcontrols.play();
}
}
/// <summary>
/// 右鍵退出功能
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
{
DialogResult dr = MessageBox.Show("確定要退出?", "question", MessageBoxButtons.OKCancel);
if (dr == DialogResult.OK)
{
// 1.this.Close(); 只是關閉當前窗口,若不是主窗體的話,是無法退出程序的,另外若有托管線程(非主線程),也無法干凈地退出;
//2.Application.Exit(); 強制所有消息中止,退出所有的窗體,但是若有托管線程(非主線程),也無法干凈地退出;
//3.Application.ExitThread(); 強制中止調用線程上的所有消息,同樣面臨其它線程無法正確退出的問題;
//4.System.Environment.Exit(0); 這是最徹底的退出方式,不管什么線程都被強制退出,把程序結束的很干凈。
Application.Exit();
//System.Environment.Exit(0);
//this.Close();
}
else
{
}
}
/// <summary>
/// 托盤右鍵顯示窗口
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 顯示ToolStripMenuItem_Click(object sender, EventArgs e)
{
if (contextMenuStrip2.Items[1].Text == "顯示")
{
this.Show();
//還原窗體顯示
WindowState = FormWindowState.Normal;
//激活窗體並給予它焦點
this.Activate();
//任務欄區顯示圖標
this.ShowInTaskbar = true;
//托盤區圖標隱藏
// notifyIcon1.Visible = false;
contextMenuStrip2.Items[1].Text = "隱藏";
}
else
{
contextMenuStrip2.Items[1].Text = "顯示";
// Form1_Deactivate(this, e);
this.notifyIcon1.Visible = true; //顯示托盤圖標
this.Hide();//隱藏窗體
this.ShowInTaskbar = false;//圖標不顯示在任務欄
}
}
/// <summary>
/// 最小化到托盤,注意deactive事件使用
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Deactivate(object sender, EventArgs e)
{
//當窗體為最小化狀態時
if (this.WindowState == FormWindowState.Minimized)
{
this.notifyIcon1.Visible = true; //顯示托盤圖標
this.Hide();//隱藏窗體
this.ShowInTaskbar = false;//圖標不顯示在任務欄
}
}
/// <summary>
/// 關閉窗口提示
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show("確定關閉?", "", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
{
e.Cancel = true;
}
// 窗體的Closing事件,里面如果使用Application.Exit(),會彈出兩次對話框詢問:
//這個是很正常的,當執行Application.Exit()時,就激活窗體的關閉事件,從而調用該事件的處理程序StartForm_FormClosing,你這樣寫相當於遞歸調用
//修改如下:
//private void StartForm_FormClosing(object sender, FormClosingEventArgs e)
// {
// if (DialogResult.Cancel == MessageBox.Show("確認退出?", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Information))
// {
// e.Cancel = true;
// }
// }
//或者用System.Environment.Exit(0);
}
/// <summary>
/// 右鍵打開音樂目錄,沒有實現自動選定文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void 打開目錄ToolStripMenuItem_Click(object sender, EventArgs e)
{
Process.Start("explorer", Path.GetDirectoryName(slist[listBox1.SelectedIndex]));//打開D盤
}
/// <summary>
/// 歌詞實現,每隔一段時間自動for篩選出匹配歌詞
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void timer1_Tick(object sender, EventArgs e)
{
if (File.Exists(Path.ChangeExtension(axWindowsMediaPlayer1.URL, ".lrc")))
{
double mctime = axWindowsMediaPlayer1.Ctlcontrols.currentPosition;
//篩選功能,有次數限制,否則窗體假死
for (int i = 0; i < dlrc.Count; i++)
{
if (mctime > dlrc[i] && mctime < dlrc[i + 1])
{
label1.Text = slrc[i];
}
}
}
else if(axWindowsMediaPlayer1.playState== WMPLib.WMPPlayState.wmppsPlaying)
{
label1.Text = "沒有歌詞文件!";
}
else
{
label1.Text = "等待中";
}
}
}
}
