C#/音乐播放器/带进度条/歌词滚动、颜色变化/桌面应用程序设计

用基本C#知识实现制作一个音乐播放器

前言

写这个博客并不是说我的作品多么高级或完美,只是希望能在一些功能方面给你们一些启发,能帮助到你们做出真正好的程序,这就足够了
话不多说,让我们开始吧~~~

截图示意

在这里插入图片描述

总体思路

首先呢,选择这种无边框窗口,我们会发现移动窗口成了问题,所以呢,就需要特意对主窗口写事件,即按下时,移动时,松开时等各是怎样,这个应该不难。

···

    Point downpoint;
    Point movepoint;
    bool ismoving;

 //实现鼠标控制窗口移动
    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        downpoint = e.Location;
        ismoving = true;
    }

    private void timermove_Tick(object sender, EventArgs e)
    {

    }
    //实现鼠标控制窗口移动(2)
    private void mainForm_MouseMove(object sender, MouseEventArgs e)
    {
        if (ismoving == true)
        {
            movepoint = e.Location;
            this.Location = new Point(
                this.Location.X + (movepoint.X - downpoint.X),
                this.Location.Y + (movepoint.Y - downpoint.Y)
                );
        }
    }
    //鼠标按键抬起窗口停止移动
    private void mainForm_MouseUp(object sender, MouseEventArgs e)
    {
        ismoving = false;
    }

····

然后就是引入WindowsMediaPlayer后我们需要实现音频文件资源的打开,这里我设置了文件过滤器,只能打开“.MP3”“.MP4”“.flac”三种文件,同时实现了基本功能,例如点击播放器的播放(暂停)键时图标的变化、歌曲继续、暂停等(所以我们用到一个bool型变量方便判断)

···

    bool isplaying = true;
    string a;//歌曲总时间(字符串)

    //点击播放:加载歌词
    private void start_Click(object sender, EventArgs e)
    {
        if (tick == 0)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "mp3音乐|*.mp3|mp4音乐|*.mp4|flac文件|*.flac";//设置文件过滤,使之只能打开.mp3/.mp4/flac三种格式的音频文件
            ofd.ShowDialog();
            string fileName = ofd.FileName;

            media.URL = fileName;
            media.Ctlcontrols.play();

            //  start_Click(object sender, EventArgs e);
            timer2.Enabled = true;
        }




        tick = 1;
        timer1.Enabled = true;
       Encoding encode = Encoding.GetEncoding("GB2312");
        
        FileStream fs = new FileStream("陈一发儿-童话镇.lrc", FileMode.Open);
        StreamReader sr = new StreamReader(fs, encode);
        string s = sr.ReadLine();
        //int xPos = 100;
        int yPos = 50;
        string a= media.currentMedia.durationString;
        stime.Text = a;
        while (s != null)
        {


            s = sr.ReadLine();
           
            if(s==null)
            {
                break;
            }
            if (s.Equals(""))
            {
                continue;
            }
            Lyric1 lyric =new Lyric1();
            lyric.minute =int.Parse(s.Substring(1,2));
            lyric.second = int.Parse(s.Substring(4,2));
            lyric.lyrics = s.Substring(10);
            lyric.tosecond = lyric.minute * 60 + lyric.second;
            //if(s.Substring(10)==null)
            //{
              
               // lyric.sminute = Convert.ToInt32(s.Substring(1, 1));
                //lyric.ssecond = Convert.ToInt32(s.Substring(5, 1));
           // }

            listLyric1.Add(lyric);
            

            yPos += 30;
        }     
        if (isplaying)
        {
            start.BackgroundImage = Properties.Resources.play_circle_o;
            isplaying = false;
            media.Ctlcontrols.pause();
            timer1.Enabled = false;
            

           
           
        }
        else
        {
            start.BackgroundImage = Properties.Resources.pause_circle_o;
            isplaying = true;
            media.Ctlcontrols.play();
            timer1.Enabled = true;
           
        }
     fs.Close();
      sr.Close();
    }

···

另一个功能有一部分也包含在上述代码中,那就是重要的歌词绘制(只不过上面主要只实现了歌词文件(“.lrc”)的读取),其实有人说用label也能显示歌词、甚至实现歌词滚动、变色,可是吧…效果不太好,一方面不流畅,另一方面显示效果也差,甚至可能有闪屏
所以我采用了GDI+绘图实现的
注意哈,GDI+绘图是不会自动变化的,需要窗口隐藏以至于无效化才会更新
所以我们需要写程序使需要的区域(不一定是整个主窗口)不断自动刷新

···

     Graphics g;//绘图对象
    int PointY=140;
    int current;
    //主窗口绘制歌词
    private void mainForm_Paint(object sender, PaintEventArgs e)
    {
  
        g = e.Graphics;

        if (tick == 2)
        {
            for (int i = 0; i < listLyric.Count; i++)
            {
                if (i == current)
                    g.DrawString(listLyric[i].lyrics, new Font("微软雅黑", 17), Brushes.LightBlue, 400, PointY + i * 50);
                else
                    g.DrawString(listLyric[i].lyrics, new Font("微软雅黑", 14), Brushes.White, 400, PointY + i * 50);
            }
        }
        else
        {
            for (int i = 0; i < listLyric1.Count; i++)
            {
                if (i == current)
                    g.DrawString(listLyric1[i].lyrics, new Font("微软雅黑", 17), Brushes.LightBlue, 400, PointY + i * 50);
                else
                    g.DrawString(listLyric1[i].lyrics, new Font("微软雅黑", 14), Brushes.White, 400, PointY + i * 50);
            }
        }
    }
    double position;
    //时钟:不停调用刷新主窗口
    private void timer1_Tick(object sender, EventArgs e)
    {
        //获取当前歌曲播放时间
         position = media.Ctlcontrols.currentPosition;
        int a = (int)position;
        int m = a / 60;
        int s = a % 60;
        time1.Text = m.ToString();
        time2.Text = s.ToString();
        PointY-=1;


        for (int i = 0; i < listLyric.Count-1; i++)
        {
            double b = listLyric[i].tosecond;
            double c = listLyric[i+1].tosecond;
          //  int positioni = (int)position;
            if (position > b && position < c)
                current = i;
       }
        this.Invalidate(UpdateRect);
    }
    Rectangle UpdateRect;
   
   //主窗口刷新
    private void mainForm_Load(object sender, EventArgs e)
    {
   
        UpdateRect = new Rectangle(0, 0, this.ClientSize.Width,
            this.ClientSize.Height - panel1.Height);
    }

···

还有一个功能是包含在上面代码里的
那就是歌曲总时间与现在时间的显示,这个的话现在时间直接读取来的时间通常是以秒为单位,我们为了显示更加直观,将其换算为正常的分与秒,总时间就采取直接显示原来的字符串形式

···

        position = media.Ctlcontrols.currentPosition;
        int a = (int)position;
        int m = a / 60;
        int s = a % 60;
        time1.Text = m.ToString();
        time2.Text = s.ToString();




        string a = media.currentMedia.durationString;
        stime.Text = a;

···

最后呢就是进度条怎么来的
这个我用了两个panel,不同的宽度,不同的颜色,通过在timer里调用增加蓝色panel的长度实现,这个我们要用到音频文件总时间,从而计算出单位timer时间里长度伸展多少,来实现进度条的功能

····

private void timer2_Tick(object sender, EventArgs e)
  {
    a = media.currentMedia.durationString;
    int timm = int.Parse(a.Substring(1,1));
    int tims = int.Parse(a.Substring(3,2));
    int tim = timm * 60 + tims;
    sizex += (610/ tim);
    if(sizex<610&& isplaying==true)
    {
        going.Size = new Size(sizex, 10);
    }
 }

···

总体就这样啦,不过,很多地方可能都没说明,例如我是额外封装了一个类 Lyric1的、还多写了一个打开歌曲的通道,以及用tick判断打开形式;上面涉及到的当前歌词变大变色也没详细说明… … 代码贴在下面,大家自己读好了

代码

···

  //Lyric1.cs
  using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace kuwo
{
class Lyric1
{
    public int minute;
    public int second;
    public int tosecond;
   
    
    public string lyrics;
    
}

}

//Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;



namespace kuwo
{
public partial class mainForm : Form
{
    List<Lyric1> listLyric = new List<Lyric1>();
    List<Lyric1> listLyric1 = new List<Lyric1>();
    int tick = 0;
    public mainForm()
    {
        InitializeComponent();
    }
    Point downpoint;
    Point movepoint;
    bool ismoving;
    //实现鼠标控制窗口移动(1)
    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        downpoint = e.Location;
        ismoving = true;
    }

    private void timermove_Tick(object sender, EventArgs e)
    {

    }
    //实现鼠标控制窗口移动(2)
    private void mainForm_MouseMove(object sender, MouseEventArgs e)
    {
        if (ismoving == true)
        {
            movepoint = e.Location;
            this.Location = new Point(
                this.Location.X + (movepoint.X - downpoint.X),
                this.Location.Y + (movepoint.Y - downpoint.Y)
                );
        }
    }
    //鼠标按键抬起窗口停止移动
    private void mainForm_MouseUp(object sender, MouseEventArgs e)
    {
        ismoving = false;
    }
    bool isplaying = true;
    string a;//歌曲总时间(字符串)



    //点击播放:加载歌词
    private void start_Click(object sender, EventArgs e)
    {
        if (tick == 0)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "mp3音乐|*.mp3|mp4音乐|*.mp4|flac文件|*.flac";//设置文件过滤,使之只能打开.mp3/.mp4/flac三种格式的音频文件
            ofd.ShowDialog();
            string fileName = ofd.FileName;

            media.URL = fileName;
            media.Ctlcontrols.play();

            //  start_Click(object sender, EventArgs e);
            timer2.Enabled = true;
        }




        tick = 1;
        timer1.Enabled = true;
       Encoding encode = Encoding.GetEncoding("GB2312");
        
        FileStream fs = new FileStream("陈一发儿-童话镇.lrc", FileMode.Open);
        StreamReader sr = new StreamReader(fs, encode);
        string s = sr.ReadLine();
        //int xPos = 100;
        int yPos = 50;
        string a= media.currentMedia.durationString;
        stime.Text = a;
        while (s != null)
        {


            s = sr.ReadLine();
           
            if(s==null)
            {
                break;
            }
            if (s.Equals(""))
            {
                continue;
            }
            Lyric1 lyric =new Lyric1();
            lyric.minute =int.Parse(s.Substring(1,2));
            lyric.second = int.Parse(s.Substring(4,2));
            lyric.lyrics = s.Substring(10);
            lyric.tosecond = lyric.minute * 60 + lyric.second;
            //if(s.Substring(10)==null)
            //{
              
               // lyric.sminute = Convert.ToInt32(s.Substring(1, 1));
                //lyric.ssecond = Convert.ToInt32(s.Substring(5, 1));
           // }

            listLyric1.Add(lyric);
            

            yPos += 30;
        }     
        if (isplaying)
        {
            start.BackgroundImage = Properties.Resources.play_circle_o;
            isplaying = false;
            media.Ctlcontrols.pause();
            timer1.Enabled = false;
            

            //"C#openfiledialog  设置文件过滤"
           
        }
        else
        {
            start.BackgroundImage = Properties.Resources.pause_circle_o;
            isplaying = true;
            media.Ctlcontrols.play();
            timer1.Enabled = true;
           
        }
     fs.Close();
      sr.Close();
    }
    //打开本地资源
    private void startplay_Click(object sender, EventArgs e)
    {
        tick = 2;

        OpenFileDialog ofd = new OpenFileDialog();
        ofd.Filter = "mp3音乐|*.mp3|mp4音乐|*.mp4|flac文件|*.flac";//设置文件过滤,使之只能打开.mp3/.mp4/flac三种格式的音频文件
        ofd.ShowDialog();
        string fileName = ofd.FileName;

        media.URL = fileName;
        media.Ctlcontrols.play();

        //  start_Click(object sender, EventArgs e);
        timer2.Enabled = true;






        timer1.Enabled = true;
        Encoding encode = Encoding.GetEncoding("GB2312");

        FileStream fs = new FileStream("陈一发儿-童话镇.lrc", FileMode.Open);
        StreamReader sr = new StreamReader(fs, encode);
        string s = sr.ReadLine();
       // int xPos = 100;
        int yPos = 50;
        string a = media.currentMedia.durationString;
        stime.Text = a;
        while (s != null)
        {


            s = sr.ReadLine();

            if (s == null)
            {
                break;
            }
            if (s.Equals(""))
            {
                continue;
            }
            Lyric1 lyric = new Lyric1();
            lyric.minute = int.Parse(s.Substring(1, 2));
            lyric.second = int.Parse(s.Substring(4, 2));
            lyric.lyrics = s.Substring(10);
            lyric.tosecond = lyric.minute * 60 + lyric.second;
            //if(s.Substring(10)==null)
            //{

            // lyric.sminute = Convert.ToInt32(s.Substring(1, 1));
            //lyric.ssecond = Convert.ToInt32(s.Substring(5, 1));
            // }

            listLyric.Add(lyric);


            yPos += 30;
        }
   
        fs.Close();
        sr.Close();
    









}
    //绘画
    Graphics g;//绘图对象
    int PointY=140;
    int current;
    //主窗口绘制歌词
    private void mainForm_Paint(object sender, PaintEventArgs e)
    {
  
        g = e.Graphics;

        if (tick == 2)
        {
            for (int i = 0; i < listLyric.Count; i++)
            {
                if (i == current)
                    g.DrawString(listLyric[i].lyrics, new Font("微软雅黑", 17), Brushes.LightBlue, 400, PointY + i * 50);
                else
                    g.DrawString(listLyric[i].lyrics, new Font("微软雅黑", 14), Brushes.White, 400, PointY + i * 50);
            }
        }
        else
        {
            for (int i = 0; i < listLyric1.Count; i++)
            {
                if (i == current)
                    g.DrawString(listLyric1[i].lyrics, new Font("微软雅黑", 17), Brushes.LightBlue, 400, PointY + i * 50);
                else
                    g.DrawString(listLyric1[i].lyrics, new Font("微软雅黑", 14), Brushes.White, 400, PointY + i * 50);
            }
        }
    }
    double position;
    //时钟:不停调用刷新主窗口
    private void timer1_Tick(object sender, EventArgs e)
    {
        //获取当前歌曲播放时间
         position = media.Ctlcontrols.currentPosition;
        int a = (int)position;
        int m = a / 60;
        int s = a % 60;
        time1.Text = m.ToString();
        time2.Text = s.ToString();
        PointY-=1;


        for (int i = 0; i < listLyric.Count-1; i++)
        {
            double b = listLyric[i].tosecond;
            double c = listLyric[i+1].tosecond;
          //  int positioni = (int)position;
            if (position > b && position < c)
                current = i;
       }
        this.Invalidate(UpdateRect);
    }
    Rectangle UpdateRect;
   
   //主窗口刷新
    private void mainForm_Load(object sender, EventArgs e)
    {
   
        UpdateRect = new Rectangle(0, 0, this.ClientSize.Width,
            this.ClientSize.Height - panel1.Height);
    }
    int sizex = 42;
    private void timer2_Tick(object sender, EventArgs e)
    {
        a = media.currentMedia.durationString;
        int timm = int.Parse(a.Substring(1,1));
        int tims = int.Parse(a.Substring(3,2));
        int tim = timm * 60 + tims;
        sizex += (610/ tim);
        if(sizex<610&& isplaying==true)
        {
            going.Size = new Size(sizex, 10);
        }
    }
    //点击播放
    private void lyricstart_Click(object sender, EventArgs e)
    {
        // tick = 1;
        if (timer1.Enabled == true)
            timer1.Enabled = false;
        else
            timer1.Enabled = true;
      
    }
}
}

···

  • 4
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值