winform动态歌词显示控件(基于ListBox与Lable)
/// <summary>/// 歌词类
/// </summary>
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("\n\n\n\n\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, "");
l.Ar = GetMiddleText(str, "");
l.Al = GetMiddleText(str, "");
l.By = GetMiddleText(str, "");
l.Offset = ToInt32(GetMiddleText(str, ""), 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>
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(@"\[(*)\]+(.*)", RegexOptions.Compiled);
MatchCollection mc = regex.Matches(s.Trim());
double time = TimeSpan.Parse("00:" + mc.Groups.Value).TotalSeconds;
string word = mc.Groups.Value;
return new LrcWord(time, word);
}
catch (Exception)
{ return null; }
}
public override string ToString()
{
return Word;
}
}
ListBox实现
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.Time >= offset)
{//如果那句歌词时间大于等于进度则显示
this.SelectedIndex = i - 1;
break;
}
}
}
}
catch (Exception)
{ }
}
}
Lable实现
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.Time >= offset)
{//如果那句歌词时间大于等于进度则显示
this.Text = CurrentLrc.Words.Word;
break;
}
}
}
}
catch (Exception)
{ }
}
}
窗体部分代码(wmp控件实现播放)
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);
}
.Net前端早该换WPF,别等了,兄弟。 怎样设置保留行号??
页:
[1]