吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2049|回复: 2
收起左侧

[其他转载] winform动态歌词显示控件(基于ListBox与Lable)

[复制链接]
遗憾迟香 发表于 2021-1-22 10:21
[C#] 纯文本查看 复制代码
    /// <summary>
    /// 歌词类
    /// </summary>
    [Serializable()]
    public class Lyric
    {
        /// <summary>
        /// 曲名
        /// </summary>
        public string Ti { get; set; }
        /// <summary>
        /// 艺术家
        /// </summary>
        public string Ar { get; set; }
        /// <summary>
        /// 专辑
        /// </summary>
        public string Al { get; set; }
        /// <summary>
        /// 制作人
        /// </summary>
        public string By { get; set; }
        /// <summary>
        /// 时间补偿值
        /// </summary>
        public int Offset { get; set; }
        /// <summary>
        /// 行数
        /// </summary>
        public int Count { get { return Words.Count; } }
        /// <summary>
        /// 文本集
        /// </summary>
        public List<LrcWord> Words { get; set; }
        /// <summary>
        /// 导出格式
        /// </summary>
        public string Export
        {
            get
            {
                StringBuilder str = new StringBuilder("");
                str.Append(string.Format("[ti:{0}]\n[ar:{1}]\n[al:{2}]\n[by:{3}]\n[offset:{4}]\r\n", Ti, Ar, Al, By, Offset));
                foreach (LrcWord i in Words)
                { str.Append(i.Export); }
                return str.ToString().Trim();
            }
        }
        /// <summary>
        /// 文本
        /// </summary>
        public string Text
        {
            get
            {
                StringBuilder str = new StringBuilder("");
                foreach (LrcWord i in Words)
                { str.Append(i.Word + "\n"); }
                return str.ToString().Trim();
            }
        }
        /// <summary>
        /// Lyrec默认构造
        /// </summary>
        public Lyric()
        {
            Words = new List<LrcWord>();
        }
        /// <summary>
        /// 创建Lrcc歌词
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static Lyric Create(string[] text)
        {
            Lyric l = new Lyric();
            foreach (string i in text)
            {
                l.Words.Add(new LrcWord(i));
            }
            return l;
        }
        /// <summary>
        /// 从字符串加载
        /// </summary>
        public static Lyric Parse(string str)
        {
            str =str.Replace(@"\n", "\n");
            string[] words = str.Split('\n');
            Lyric l = new Lyric();
            l.Ti = GetMiddleText(str, "[ti:", "]");
            l.Ar = GetMiddleText(str, "[ar:", "]");
            l.Al = GetMiddleText(str, "[al:", "]");
            l.By = GetMiddleText(str, "[by:", "]");
            l.Offset = ToInt32(GetMiddleText(str, "[offset:", "]"), 0);
            l.Words = new List<LrcWord>();
            foreach (string i in words)
            {
                LrcWord lw = LrcWord.Parse(i);
                if (lw != null)
                { l.Words.Add(lw); }
            }
            if (l.Words.Count == 0)
            { return null; }
            return l;
        }
        /// <summary>
        /// 从文件加载
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="en">编码</param>
        public static Lyric FromFile(string path, Encoding en)
        {
            string str = File.ReadAllText(path, en);
            return Parse(str);
        }
        /// <summary>
        /// 保存歌词
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="en">编码</param>
        public void Save(string path, Encoding en)
        {
            File.Delete(path);
            File.AppendAllText(path, Export, en);
        }
        /// <summary>
        /// 保存为文本
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="en">编码</param>
        public void SaveText(string path, Encoding en)
        {
            File.Delete(path);
            File.AppendAllText(path, Text, en);
        }
        /// <summary>
        /// 取出中间字符串
        /// </summary>
        /// <param name="str">源字符串</param>
        /// <param name="left">左</param>
        /// <param name="right">右</param>
        /// <returns>成功返回结果,失败返回空</returns>
        private static string GetMiddleText(string str, string left, string right)
        {
            if (str == null || left == null || right == null) { return ""; }
            if (str == "" || left == "" || right == "") { return ""; }
            int a = str.IndexOf(left, 0);
            int b = str.IndexOf(right, a + 1);
            if (a < 0 || b < 0)
            { return ""; }
            else
            {
                a = a + left.Length;
                b = b - a;
                if (a < 0 || b < 0)
                { return ""; }
                return str.Substring(a, b);
            }
        }
        /// <summary>
        /// 字符串转整数
        /// </summary>
        /// <param name="str">字符串</param>
        /// <param name="str">默认值</param>
        /// <returns>成功返回结果,失败返回默认值</returns>
        private static int ToInt32(string str, int defultValue = 0)
        {
            try { return int.Parse(str); }
            catch (Exception)
            { return defultValue; }
        }
    }
    /// <summary>
    /// 歌词文本类
    /// </summary>
    [Serializable()]
    public class LrcWord
    {
        /// <summary>
        /// 时间
        /// </summary>
        public double Time { get; set; }
        /// <summary>
        /// 文本
        /// </summary>
        public string Word { get; set; }
        /// <summary>
        /// 导出格式
        /// </summary>
        public string Export
        { get { return string.Format("[{0}:{1:f3}]{2}\n", ((int)Math.Floor(Time / 60)).ToString("00"), Time % 60, Word); } }
        /// <summary>
        /// LrcWord有参构造
        /// </summary>
        /// <param name="time">时间</param>
        /// <param name="word">文本</param>
        private LrcWord(double time, string word)
        {
            Time = time;
            Word = word;
        }
        /// <summary>
        /// LrcWord有参构造
        /// </summary>
        /// <param name="text">文本</param>
        public LrcWord(string text)
        { Word = text; }
        /// <summary>
        /// 将字符串转换为歌词文本对象
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static LrcWord Parse(string s)
        {
            try
            {
                Regex regex = new Regex(@"\[([0-9.:]*)\]+(.*)", RegexOptions.Compiled);
                MatchCollection mc = regex.Matches(s.Trim());
                double time = TimeSpan.Parse("00:" + mc[0].Groups[1].Value).TotalSeconds;
                string word = mc[0].Groups[2].Value;
                return new LrcWord(time, word);
            }
            catch (Exception)
            { return null; }
        }
        public override string ToString()
        {
            return Word;
        }
    }

ListBox实现
[C#] 纯文本查看 复制代码
    public class LrcView : ListBox
    {
        private Lyric currentLrc;
        /// <summary>
        /// 当前歌词
        /// </summary>
        public Lyric CurrentLrc
        {
            get { return currentLrc; }
            set
            {
                LoadLrc(value);
                currentLrc = value;
            }
        }
        /// <summary>
        /// 设置超前时间
        /// </summary>
        public double Offset { get; set; }
        /// <summary>
        /// 加载歌词
        /// </summary>
        /// <param name="l"></param>
        private void LoadLrc(Lyric l)
        {
            this.Items.Clear();
            if (l != null)
            {
                foreach (var item in l.Words)
                {
                    this.Items.Add(item);
                }
            }
        }
        /// <summary>
        /// 根据播放进度展示歌词
        /// </summary>
        /// <param name="t"></param>
        public void Play(double t)
        {
            try
            {
                //当歌词不为空的时候滚动
                if (CurrentLrc != null)
                {
                    //计算超前时间
                    double offset = t + CurrentLrc.Offset + Offset;
                    for (int i = 0; i < CurrentLrc.Words.Count; i++)
                    {//循环遍历歌词文本
                        if (CurrentLrc.Words[i].Time >= offset)
                        {//如果那句歌词时间大于等于进度则显示
                            this.SelectedIndex = i - 1;
                            break;
                        }
                    }
                }
            }
            catch (Exception)
            { }
        }
    }

Lable实现
[C#] 纯文本查看 复制代码
    public class LrcLabel : Label
    {
        private Lyric currentLrc;
        /// <summary>
        /// 当前歌词
        /// </summary>
        public Lyric CurrentLrc
        { get; set; }
        /// <summary>
        /// 设置超前时间
        /// </summary>
        public double Offset { get; set; }
        /// <summary>
        /// 根据播放进度展示歌词
        /// </summary>
        /// <param name="t"></param>
        public void Play(double t)
        {
            try
            {
                //当歌词不为空的时候滚动
                if (CurrentLrc != null)
                {
                    //计算超前时间
                    double offset = t + CurrentLrc.Offset + Offset;
                    for (int i = 0; i < CurrentLrc.Words.Count; i++)
                    {//循环遍历歌词文本
                        if (CurrentLrc.Words[i].Time >= offset)
                        {//如果那句歌词时间大于等于进度则显示
                            this.Text = CurrentLrc.Words[i - 1].Word;
                            break;
                        }
                    }
                }
            }
            catch (Exception)
            { }
        }
    }

窗体部分代码(wmp控件实现播放)
[C#] 纯文本查看 复制代码
        private void Form1_Load(object sender, EventArgs e)
        {
            axWindowsMediaPlayer1.URL = "leinov - 程序员之歌.mp3";
            Lyric l = Lyric.FromFile("leinov - 程序员之歌.lrc", Encoding.Default);
            lrcView1.CurrentLrc = l;
            lrcLabel1.CurrentLrc = l;
            timer1.Start();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            double t = axWindowsMediaPlayer1.Ctlcontrols.currentPosition;
            lrcView1.Play(t);
            lrcLabel1.Play(t);
        }

2021-1-22 10-18-56.png

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

coolcalf 发表于 2021-1-22 11:32
.Net前端早该换WPF,别等了,兄弟。
wgw555 发表于 2021-1-31 14:07
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 19:33

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表