在C#中播放音乐主要有三种方式:1、System.Media.SoundPlay;2、MCI接口;3、MediaPlayer控件。SoundPlay是专门用来播放声音的,即.wav文件,使用方法比较简单。MediaPlayer控件是系统自带的播放器,关于它的介绍已经很多了。
今天我想为大家介绍的MCI接口,关于MCI接口的介绍,大家可以参考MSDN,这里我们只是介绍具体的用法。首先,我们需要定义一个枚举类型来描述播放器的状态。
public enum PlayState : byte { Playing = 1, Puased = 2, Stopped = 3, }
接下来,为了便于后面的继续,我们对MCI接口做了一个封装:
class WAPI { [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern int GetShortPathName( string lpszLongPath, string shortFile, int cchBuffer ); [DllImport("winmm.dll", EntryPoint = "mciSendString", CharSet = CharSet.Auto)] public static extern int mciSendString( string lpstrCommand, string lpstrReturnString, int uReturnLength, int hwndCallback ); }
关于这两个API函数,大家可以在MSDN找到相关说明。接下来,我们来构建播放器的类:
public class MPlayer { //定义歌曲地址 private string Url = string.Empty; //定义歌曲结构的实例 private Media m = new Media(); //构造函数 public MPlayer() { m.Position = 0; m.State = PlayState.Stopped; m.Volume = 0; m.Speed = 1000; m.Duration = 0; } //FileName属性 public string FileName { set { Url = string.Empty; string Name = value; m.Position = 0; Url = Url.PadLeft(260, ' '); WAPI.GetShortPathName(Name, Url, Url.Length); Url = GetFileUrl(Url); InitDevice(); } } //设备初始化 private void InitDevice() { string DeviceID = GetDeviceID(Url);//返回类型 WAPI.mciSendString("Close All", null, 0, 0);//关闭所有设备 if (DeviceID != "RealPlay") { string MciCommand = String.Format("Open {0} type {1} Alias Media", Url, DeviceID); WAPI.mciSendString(MciCommand, null, 0, 0);//初始化设备 m.State = PlayState.Stopped; } } //获取设备ID private string GetDeviceID(string Url) { string Result = string.Empty; Url = Url.ToUpper().Trim(); if (Url.Length < 3) { return Url; } switch (Url.Substring(Url.Length - 3)) { case "MID": Result = "Sequencer"; break; case "RMI": Result = "Sequencer"; break; case "IDI": Result = "Sequencer"; break; case "WAV": Result = "Waveaudio"; break; case "ASX": Result = "MPEGVideo2"; break; case "IVF": Result = "MPEGVideo2"; break; case "LSF": Result = "MPEGVideo2"; break; case "LSX": Result = "MPEGVideo2"; break; case "P2V": Result = "MPEGVideo2"; break; case "WAX": Result = "MPEGVideo2"; break; case "WVX": Result = "MPEGVideo2"; break; case ".WM": Result = "MPEGVideo2"; break; case "WMX": Result = "MPEGVideo2"; break; case "WMP": Result = "MPEGVideo2"; break; case ".RM": Result = "RealPlay"; break; case "RAM": Result = "RealPlay"; break; case ".RA": Result = "RealPlay"; break; case "MVB": Result = "RealPlay"; break; default: Result = "MPEGVideo"; break; } return Result; } //得到当前路径 private string GetFileUrl(string FileName) { FileName = FileName.Trim();//去掉空格 if (FileName.Length > 1)//判断是否为空(name包含'\0') { FileName = FileName.Substring(0, FileName.Length - 1);//去掉'\0' } return FileName; } //判断初始化后设备是否准备好接受命令 public bool IsReady() { string Ready = new string(' ', 10); WAPI.mciSendString("Status Media Ready", Ready, Ready.Length, 0); Ready = Ready.Trim(); if (Ready.Contains("true")) { return true; } else { return false; } } //播放 public void Play() { if (m.State != PlayState.Playing) { WAPI.mciSendString("Play Media", null, 0, 0); m.State = PlayState.Playing; } } //停止 public void Stop() { if (m.State != PlayState.Stopped) { WAPI.mciSendString("Stop Media", null, 0, 0); m.State = PlayState.Stopped; } } //暂停 public void Puase() { if (m.State == PlayState.Playing) { WAPI.mciSendString("Pause Media", null, 0, 0); m.State = PlayState.Puased; } } //恢复播放 public void Resume() { int RefInt = WAPI.mciSendString("Resume Media", null, 0, 0); m.State = PlayState.Playing; } //属性Duration public int Duration { get { WAPI.mciSendString("Set Media Time Format Milliseconds", null, 0, 0);//设置时间格式单位为毫秒 m.Duration = GetDuration(); return m.Duration; } } private int GetDuration() { string Length = string.Empty; Length = Length.PadLeft(20, ' ');//设置定长字符串long是19位,足够表示时间了 WAPI.mciSendString("Status Media Length", Length, Length.Length, 0); Length = Length.Trim(); if (Length.Length > 1) { Length = Length.Substring(0, Length.Length - 1); return (int)(long.Parse(Length) / 1000); } return 0; } //属性State public PlayState State { get { return m.State; } } public string PositionString { get { string mm = (this.Position / 60).ToString("00"); string ss = (this.Position % 60).ToString("00"); return mm + ":" + ss; } } public string DurationString { get { string mm = (this.Duration / 60).ToString("00"); string ss = (this.Duration % 60).ToString("00"); return mm + ":" + ss; } } //设置获取当前时间 public int Position { get { string Position = string.Empty; Position = Position.PadLeft(20, ' ');//long表示范围是19位 WAPI.mciSendString("Status Media Position", Position, Position.Length, 0); Position = Position.Trim(); if (Position.Length > 1) { m.Position = (int)(long.Parse(Position) / 1000);//以秒返回 } return m.Position; } set { string Command = String.Format("Seek Media to {0}", value*1000); WAPI.mciSendString(Command, null, 0, 0);//使播放停止 m.State = PlayState.Stopped; m.Position = value*1000; Play(); } } //设置静音 public void VolumeOff(bool IsOff) { string SetOnOff = string.Empty; if (IsOff) SetOnOff = "Off"; else SetOnOff = "On"; string MciCommand = String.Format("Set Audio Media {0}", SetOnOff); WAPI.mciSendString(MciCommand, null, 0, 0); } //Volume public int Volume { get { return m.Volume; } set { if (value >= 0) { m.Volume = value; string MciCommand = String.Format("Set Audio Media Volume To {0}", m.Volume); WAPI.mciSendString(MciCommand, null, 0, 0); } } } //定义歌曲结构 private struct Media { public int Position; public PlayState State; public int Volume; public int Speed; public int Duration; } }
关于这个类,我想说两点,第一:在设置Position属性即歌曲的进度时,我们对其赋值为value*1000.为什么要乘1000呢?因为在获取Position时为们做了单位转换,除了1000,所以这里要乘以1000,否则程序将不起作用。第二:使用MCI播放的时候,经常会发出嘶嘶的杂音,我的解决办法是,在播放前设置歌曲进度为1秒,即歌曲并不从头开始播放,这样就可以跳过去了,呵呵。好吧,就这样了,睡觉啦!