基于C#的音乐播放器主Form实现代码
程序员文章站
2024-02-17 08:39:28
本文所述为一个由c#编写的音乐播放器的主form代码,里面有一些小技巧还是不错的,现共享给大家参考一下。里面有播放器背景设置、线程定义、调用读取文件目录方法、播放时间计数器...
本文所述为一个由c#编写的音乐播放器的主form代码,里面有一些小技巧还是不错的,现共享给大家参考一下。里面有播放器背景设置、线程定义、调用读取文件目录方法、播放时间计数器、设置lv背景、获取播放歌曲、播放按钮,切换播放or暂停、切换歌曲到下一首,调用切歌方法、显示播放列表、歌词局中、播放窗体最小化隐藏到托盘设置、进度条滚动模块、从歌曲列表中删除文件等等功能。且各个功能模板均备有较为详细的注释,便于大家阅读理解。
程序主要代码如下:
using system; using system.collections.generic; using system.componentmodel; using system.data; using system.drawing; using system.linq; using system.text; using system.windows.forms; using system.io; using system.drawing.imaging; using system.threading; namespace mymusicbox { public partial class mainform : form { public mainform() { initializecomponent(); setstyle(controlstyles.userpaint, true); setstyle(controlstyles.optimizeddoublebuffer, true); setstyle(controlstyles.allpaintinginwmpaint, true); setstyle(controlstyles.doublebuffer, true); } song mysong = null;//播放的歌曲对象 listviewitem itemlrc;//打开歌词路径项 bitmap bm ;//用于动态设置lv背景 public savinginfo sa = null;//持久化信息类 thread thread;//后台线程 #region 加载事件 private void mainform_load(object sender, eventargs e) { //调用读取配置文件方法 path.readpath(); //窗体背景设置为配置文件中的图片 this.backgroundimage = image.fromfile(path.bgpath); //调用读取文件目录方法 path.readsong(); //读取播放列表 sa = new savinginfo(); sa.loadplaylist(); //绑定lv bindalllv(); bindplaylv(); setlv(); setlrcbg(); timer1.enabled = path.playing; //显示时间 lbltime.text = system.datetime.now.tostring(); //两个lbl用来根据歌曲总长和播放长度显示进度,设置位置重叠 lblruning.location = lbllong.location; //启动线程 thread = new thread(renovate); thread.isbackground = true; thread.start(); } #endregion #region 后台刷新 /// <summary> /// 时间计数状态等刷新 /// </summary> private void renovate() { //while (true) //{ // //计数 // count(); // //获取当前时间 // lbltime.text = system.datetime.now.tostring(); // //无歌曲提示,如果播放列表为空且当前播放列表为显示状态 // if (lvplay.items.count == 0 && lvplay.visible) // lblts.visible = true; // else // lblts.visible = false; // thread.sleep(1000); //} } #endregion #region 设置lv背景 /// <summary> /// 设置lv背景 /// </summary> public void setlv() { bm = new bitmap(this.backgroundimage, this.width, this.height); //绘制矩形,定义起始位置和宽高 rectangle r = new rectangle(lvplay.location.x, lvplay.location.y, lvplay.width, lvsong.height); //按矩形尺寸和起始位置截取bm的一部分 bm= bm.clone(r,bm.pixelformat); //把截取到的图片设置为lv背景,达到与主窗体背景完美契合的效果 lvsong.beginupdate(); lvsong.backgroundimage = (image)bm; lvsong.endupdate(); lvplay.beginupdate(); lvplay.backgroundimage = (image)bm; lvplay.endupdate(); } #endregion #region 获取歌曲 /// <summary> /// 获取播放歌曲 /// </summary> private void getsong() { //接收播放歌曲方法,获得一个歌曲对象 this.mysong = playlist.play(); //如果歌曲对象不为空 if (mysong != null) { //播放器路径设置为该歌曲路径 wmp.url = mysong.filename; //调用方法,显示歌曲名、歌手 lblname.text = playlist.getname(); lblsinger.text = playlist.getsinger(); mysong.songstate = songplaystate.played;//修改播放状态 //播放按钮图片修改为暂停图片 btnplay.image = image.fromfile("images\\stop.png"); try { //读取歌词路径 path.readlrc(); addlrc(); //启动一个定时器,此定时器只控制歌词轮播 timer2.start(); } catch (exception) { lrcnull(); itemlrc = new listviewitem(); itemlrc.subitems.add("找不到该歌曲歌词文件!"); itemlrc.forecolor = color.blue; itemlrc.font = new font("微软雅黑", 14.25f, ((fontstyle)((fontstyle.bold | fontstyle.underline))), graphicsunit.point, ((byte)(134))); lvlrc.items.add(itemlrc); } } } #endregion #region 主定时器 //定时器1 private void timer1_tick(object sender, eventargs e) { if (path.songpath == "") { timer1.enabled = false; return; } //如果当前无播放歌曲,调用获取歌曲的方法 if (this.mysong == null) { getsong(); } //自动下一首,如果当前播放完毕 if (this.wmp.playstate == wmplib.wmpplaystate.wmppsstopped) { this.mysong = null; // 将歌曲设为空 path.lrcpath = ""; path.diclrc.clear(); playmodel(); playlist.playnext(); thread.sleep(1000); } // 切歌,当前有播放歌曲且播放状态为cut if (this.mysong != null && this.mysong.songstate == songplaystate.cut) { this.wmp.url = "";//置空 timer2.stop(); path.diclrc.clear(); path.lrcpath = ""; this.mysong = null; } //如果当前有播放歌曲,需要获取的一些属性 if (wmp.url!="") { //设置当前播放歌曲颜色 songcolor(); //获取音量控件显示值,根据控制刻度数量计算 this.trackbar1.value = wmp.settings.volume / 10; //歌曲时间显示,一个是总长度,一个是已播放长度,字符串类型 lblall.text = wmp.currentmedia.durationstring; lblrun.text = wmp.ctlcontrols.currentpositionstring; //进度条,使用了两个lbl控件,歌曲长度/已播放长度=lbl1的宽/lbl2的宽 //乘1000为防止数据过小出现错误 double temp = (wmp.currentmedia.duration*1000) / (wmp.ctlcontrols.currentposition*1000); double width = lbllong.width; double avg = width / temp; //判断>1为了防止avg数值小于int界限 if(avg>1) lblruning.width = convert.toint32(avg); picrun.left = lblruning.right; //托盘显示播放歌曲 this.notifyicon1.text =lblname.text + lblsinger.text; } } #endregion #region 播放按钮 /// <summary> /// 播放按钮,切换播放or暂停 /// </summary> private void btnplay_click(object sender, eventargs e) { if(!timer1.enabled) timer1.start(); //如果当前为正在播放 if (wmp.playstate == wmplib.wmpplaystate.wmppsplaying) { //暂停播放 wmp.ctlcontrols.pause(); //按钮图片修改为播放 btnplay.image = image.fromfile("images\\play.png"); //停止控制歌词滚动的定时器 if (timer2.enabled) timer2.stop(); } else if (wmp.playstate == wmplib.wmpplaystate.wmppspaused) { //开始播放 wmp.ctlcontrols.play(); //按钮图片修改为暂停 btnplay.image = image.fromfile("images\\stop.png"); //启动歌词滚动 if (!timer2.enabled&&path.diclrc.count>0) timer2.start(); } } #endregion #region 切歌 //切换下一首,调用切歌方法 private void btnright_click(object sender, eventargs e) { playlist.cut(false); } //上一首,调用切歌方法 private void btnleft_click(object sender, eventargs e) { playlist.cut(true); } #endregion #region 音量 //静音,静音!=音量为0 private void btnmodel_click(object sender, eventargs e) { //如果播放器非静音状态,前景文字显示红叉,状态改为静音 if (wmp.settings.mute == false) { btnsound.text = "×"; wmp.settings.mute = true; } else//反之,已是静音状态,清空红叉,设置非静音状态 { btnsound.text = ""; wmp.settings.mute = false; } } //设置音量,此事件为控制刻度值变化时 private void trackbar1_scroll(object sender, eventargs e) { //音量设置为控制刻度*10(因为初始化的时候是/10) wmp.settings.volume = this.trackbar1.value * 10; } #endregion #region 歌曲列表操作 /// <summary> /// 绑定所有歌曲lv数据 /// </summary> private void bindalllv() { //如果所有歌曲集合为空,结束 if (playlist.song == null) return; lvsong.items.clear(); //遍历集合绑定到所有歌曲lv foreach (song s in playlist.song) { listviewitem item = new listviewitem(s.name); item.tag = s; item.subitems.add(s.singer); lvsong.items.add(item); } } //点击显示所有歌曲 private void tslblall_click(object sender, eventargs e) { //隐藏播放列表 lvplay.visible = false; //两个lv位置重叠 lvsong.location = lvplay.location; //点击后改变背景色 tslblall.backcolor = color.silver; tslblplay.backcolor = color.transparent; //显示所有歌曲lv lvsong.visible = true; } //点击显示播放列表 private void tslblplay_click(object sender, eventargs e) { //调用绑定播放lv数据 bindplaylv(); //背景色改变 tslblplay.backcolor = color.silver; tslblall.backcolor = color.transparent; //隐藏所有歌曲lv lvsong.visible = false; //显示播放lv lvplay.visible = true; } /// <summary> /// 绑定播放列表 /// </summary> private void bindplaylv() { //如果播放集合不为空 if (playlist.play!=null) { lvplay.items.clear(); //遍历集合绑定播放lv foreach (song s in playlist.play) { int id = lvplay.items.count + 1; s.id = id; listviewitem item = new listviewitem(id.tostring()); item.subitems.add(s.name); item.tag = s; lvplay.items.add(item); } } } /// <summary> /// 歌曲计数 /// </summary> private void count() { //if (lvsong.visible) // lblcount.text = "已选" + lvsong.checkeditems.count + "\\总" + lvsong.items.count; //if (lvplay.visible) // lblcount.text = "总" + lvplay.items.count; } #endregion #region 歌词操作 /// <summary> /// 设置歌词背景 /// </summary> public void setlrcbg() { bm = new bitmap(this.backgroundimage, this.width, this.height); //绘制矩形,定义起始位置和宽高 rectangle r = new rectangle(lvlrc.location.x, lvlrc.location.y, lvlrc.width, lvlrc.height); //按矩形尺寸和起始位置截取bm的一部分 bm = bm.clone(r, pixelformat.undefined); //把截取到的图片设置为lv背景,达到与主窗体背景完美契合的效果 lvlrc.beginupdate(); lvlrc.backgroundimage = (image)bm; lvlrc.endupdate(); } int nullcount;//记录空行位置 /// <summary> /// 设置空行,使歌词局中 /// </summary> private void lrcnull() { lvlrc.items.clear(); nullcount = (int)math.ceiling(convert.todouble(lvlrc.height / 30 / 2)); for (int i = 0; i <= nullcount; i++) { lvlrc.items.add(""); } } /// <summary> /// 添加歌词 /// </summary> private void addlrc() { lrcnull(); foreach (string key in path.diclrc.keys) { listviewitem item = new listviewitem(); item.subitems.add(path.diclrc[key]); item.tag = key; lvlrc.items.add(item); } } //只控制歌词轮播 private void timer2_tick(object sender, eventargs e) { //调用显示歌词的方法 showlrc(); } /// <summary> /// 显示歌词 /// </summary> private void showlrc() { foreach (listviewitem item in lvlrc.items) { if (item.tag == null) continue; if (item.tag.tostring() == lblrun.text ) { item.forecolor = color.darkorange; item.font = new font("华文琥珀", 16f, fontstyle.regular, graphicsunit.point, ((byte)(134))); lvlrc.items[item.index -1].forecolor = color.silver; lvlrc.items[item.index - 1].font = new font("微软雅黑", 12f, fontstyle.regular, graphicsunit.point, ((byte)(134))); if (item.index + 1<lvlrc.items.count) lvlrc.items[item.index+1].ensurevisible(); } } } #endregion #region 窗体隐藏到托盘设置 //最小化到托盘 private void btnmix_click(object sender, eventargs e) { this.hide(); } //主窗体大小状态变化时 private void mainform_sizechanged(object sender, eventargs e) { if (this.windowstate == formwindowstate.minimized) { //启动一个控件,该控制可以让程序在右下角显示图标,需要提前设置该控制显示的图标图片 this.notifyicon1.visible = true; } } //托盘显示,双击显示窗体 private void notifyicon1_mousedoubleclick(object sender, mouseeventargs e) { showmain(); } /// <summary> /// 显示主窗体 /// </summary> public void showmain() { if (!this.visible) { this.topmost = true; this.show(); this.topmost = false; } else { this.topmost = true; this.topmost = false; } } //托盘打开窗体 private void tsmishow_click(object sender, eventargs e) { showmain(); } //托盘退出 private void tsmiexit_click(object sender, eventargs e) { application.exit(); } #endregion #region 窗体位移 point mouseoff;//鼠标移动位置变量 bool leftflag;//标记是否为左键 private void pnlmain_mousedown(object sender, mouseeventargs e) { if (e.button == mousebuttons.left) { mouseoff = new point(-e.x, -e.y); //得到变量的值 leftflag = true; //点击左键按下时标注为true; } } private void pnlmain_mousemove(object sender, mouseeventargs e) { if (leftflag) { point mouseset = control.mouseposition; mouseset.offset(mouseoff.x, mouseoff.y); //设置移动后的位置 location = mouseset; } } private void pnlmain_mouseup(object sender, mouseeventargs e) { if (leftflag) { leftflag = false;//释放鼠标后标注为false; } } #endregion #region 进度条滚动块移动 int runx;//记录滚动块初始位置 private void picrun_mousedown(object sender, mouseeventargs e) { runx = e.x; } //释放鼠标位移,进度前进 private void picrun_mouseup(object sender, mouseeventargs e) { picrun.left += e.x - runx - picrun.width / 2; if (picrun.left > lbllong.right) picrun.left = lbllong.right; if(picrun.left<lbllong.left) picrun.left = lbllong.left; if (mysong != null) { lblruning.width = picrun.right- lblruning.left; double temp = (lbllong.width*1000.0 )/ (lblruning.width*1000.0); wmp.ctlcontrols.currentposition = wmp.currentmedia.duration / temp; } } #endregion #region 歌曲增删操作 //添加歌曲到播放列表 private void tsmiadd_click(object sender, eventargs e) { if (lvsong.checkeditems.count > 0) { foreach (listviewitem item in lvsong.checkeditems) { // 遍历播放集合,如果存在不添加 foreach (song s in playlist.play) { if (s.name == item.text) { playlist.play.remove(s); break; } } playlist.play.add(item.tag as song); } } } //所有歌曲:删除选中歌曲 private void tsmidel_click(object sender, eventargs e) { foreach (listviewitem item in lvsong.items) { if (item.checked) { playlist.song.remove(item.tag as song); } } bindalllv(); } //全选歌曲 private void tsmicheck_click(object sender, eventargs e) { foreach (listviewitem item in lvsong.items) { if (tsmicheck.text == "全部选中") { item.checked = true; if(item.index+1==lvsong.items.count) tsmicheck.text = "取消选中"; } else { item.checked = false; if (item.index + 1 == lvsong.items.count) tsmicheck.text = "全部选中"; } } } //选中项的同时选中复选框 private void lvsong_mousedown(object sender, mouseeventargs e) { if (lvsong.selecteditems.count > 0 && e.button == mousebuttons.left) { lvsong.selecteditems[0].checked = true; } } //播放列表删除事件 private void tsmiplaydel_click(object sender, eventargs e) { foreach (listviewitem item in lvplay.items) { if (item.selected) { //playlist.id = (lvplay.items[item.index+1].tag as song).id; //this.song = null; playlist.play.remove(item.tag as song); } } bindplaylv(); } //清空播放列表 private void tsmiplayclear_click(object sender, eventargs e) { playlist.play.clear(); this.mysong = null; bindplaylv(); } //从播放列表删除文件 private void tsmiplaydelfile_click(object sender, eventargs e) { if (lvplay.selecteditems.count > 0) { delfile(lvplay.selecteditems[0]); } } /// <summary> /// 删除某项对应文件 /// </summary> /// <param name="item"></param> private void delfile(listviewitem item) { try { string path = (item.tag as song).filename; file.delete(path); bindalllv(); bindplaylv(); } catch (exception) { messagebox.show("该文件为只读文件或用户权限不够,无法删除!"); } } //从所有歌曲中删除文件 private void tsmidelfile_click(object sender, eventargs e) { if (lvsong.selecteditems.count > 0) { delfile(lvsong.selecteditems[0]); } } //双击列表项播放歌曲 private void lvplay_doubleclick(object sender, eventargs e) { if (!timer1.enabled) { playlist.id = (lvplay.selecteditems[0].tag as song).id; timer1.start(); } if (lvplay.selecteditems.count > 0) { playlist.id = (lvplay.selecteditems[0].tag as song).id; this.mysong = null; } } #endregion #region 设置 //跳转设置窗体 private void btnset_click(object sender, eventargs e) { setform set = new setform(); set.parent = this;//把主窗体传过去 set.show(this); } #endregion #region 回滚 /// <summary> /// 路径重置后 /// </summary> public void back() { bindalllv(); playlist.update(); timer1.start(); } #endregion #region 退出 //关闭时保存列表 private void mainform_formclosing(object sender, formclosingeventargs e) { if (path.savelist) sa.saveplaylist(); } //面板退出 private void btnexit_click(object sender, eventargs e) { if (path.exit) { application.exit(); } else { this.hide(); } } #endregion #region 背景颜色等变换控制 private void btnleft_mouseenter(object sender, eventargs e) { ((button)sender).backgroundimage = image.fromfile("images//allbtn_highlight.png"); } private void btnleft_mouseleave(object sender, eventargs e) { ((button)sender).backgroundimage = null; } private void tslblplay_mouseenter(object sender, eventargs e) { ((toolstriplabel)sender).backgroundimage = image.fromfile("images//album_bkg_wubian.png"); } private void tslblplay_mouseleave(object sender, eventargs e) { ((toolstriplabel)sender).backgroundimage = null; } //选中改变颜色 private void lvsong_itemchecked(object sender, itemcheckedeventargs e) { foreach (listviewitem item in lvsong.items) { if (item.checked) { item.forecolor = color.darkorange; } else { item.forecolor = color.dimgray; } } } /// <summary> /// 当前播放歌曲改变颜色 /// </summary> private void songcolor() { foreach (listviewitem item in lvplay.items) { if (item.subitems[1].text == lblname.text) { item.forecolor = color.deepskyblue; } else { item.forecolor = color.white; } } } #endregion #region 选择歌词 private void lvlrc_mousedown(object sender, mouseeventargs e) { if (lvlrc.selecteditems.count>0&&lvlrc.selecteditems[0] == itemlrc) { if (path.openlrc()) { addlrc(); //启动一个定时器,此定时器只控制歌词轮播 timer2.start(); } } } #endregion #region 窗体最大化设置 size now;//原始尺寸 point pn;//原始位置 //最大化 private void btnmax_click(object sender, eventargs e) { size max = new size(screen.primaryscreen.workingarea.width - 10, screen.primaryscreen.workingarea.height - 20); if (this.size != max) { pn = this.location; now= this.size; this.size = max; this.left = 5; this.top = 5; btnmax.image = image.fromfile("images//max1.png") ; } else { this.location = pn; this.size = now; btnmax.image = image.fromfile("images//max.png"); } setlv(); setlrcbg(); } #endregion #region 歌词、mv切换 private void tsmilrc_click(object sender, eventargs e) { lvlrc.visible = true; wmp.visible = false; tsmilrc.backcolor = color.lawngreen; tsmimv.backcolor = color.transparent; } private void tsmimv_click(object sender, eventargs e) { wmp.location = lvlrc.location; wmp.size = lvlrc.size; lvlrc.visible = false; wmp.visible = true; tsmilrc.backcolor = color.transparent; tsmimv.backcolor = color.lawngreen; } #endregion #region 播放模式切换 /// <summary> /// 播放模式 /// </summary> private void playmodel() { if (tsmione.checked) { playlist.playone(); } else if (tsmisj.checked) { playlist.playrandom(); } } private void tsmixh_click(object sender, eventargs e) { toolstripmenuitem ts=((toolstripmenuitem)sender); foreach(toolstripmenuitem item in tsmimodel.dropdownitems) { if (ts.checked && ts == item) { continue; } else { item.checked = false; } } } #endregion } }
希望本文所述示例对大家的c#程序开发能够起到一定的借鉴价值。