C#winfrom播放器动态加载歌词

本文介绍了一种在C#播放器中实现歌词与歌曲同步滚动的方法,利用VisualStudio2013和.net技术,通过读取.lrc文件并解析歌词时间戳,使歌词能够随着音乐播放进度实时更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上周我们进行了结业项目答辩,是播放器项目。有一个关于播放器变唱歌边加载歌词的方法特别有意思,像酷狗那样子歌词和歌曲同步滚播的样子。

这里的工具是Visual Studio 2013,使用语言是C#和.net技术。

 首先我们使用File.Exists(@"文件路径")判断lrc歌词文件是否存在,如果存在的话读取lrc文件。

这里可以用正则表达式,也可以用一个二维数组或两个数组。本文是用的二维数组。

 lrc文件也是文本文件,一句歌词就是一行文本。简单点理解就像数据库中的DataReader,一次读取一行文本(记录),然后我们使用substring方法分别截取到文本内的时间和歌词,放到数组中。

文件大概就是这样子的。

我们读取到了之后,播放器有一个属性,Ctlcontrols.currentPositionString:string; 获取当前进度,返回一个字符串格式的值。如“00:23”

我们拿到这个值和“保存时间”的数组里的值进行匹配,判断media player播放的时间=此行时间,则让此行高亮。(用定时器一直刷新,保持同步)

 

如此,就可以达到像酷狗那样子歌词和歌曲同步滚播的样子了。

 

最后附上源代码

复制代码
 1 #region 歌词
 2         string[,] lrc = new string[2, 500];//保存歌词和当前进度
 3         /// <summary>
 4         /// 读取并显示歌词
 5         /// </summary>
 6         public void ShowLrc()
 7         {
 8             if (this.axWindowsMediaPlayer2.playState == WMPLib.WMPPlayState.wmppsPlaying)
 9             {
10                 try
11                 {
12                     //using:作用是使用完成后自动释放内存
13                     //StreamReader:作用是用特定的编码从字节流中读取字节
14                     using (StreamReader sr = new StreamReader(KTVUtil.songPath + @"\" + PlayList.PlayingSongName() + ".lrc", Encoding.Default))
15                     {
16                         String line;
17                         //循环读取每一行歌词
18                         while ((line = sr.ReadLine()) != null)
19                         {
20                             //将读取到的歌词存放到数组中
21                             for (int i = 0; i < 500; i++)
22                             {
23                                 if (lrc[0, i] == null)
24                                 {
25                                     lrc[0, i] = line.Substring(10, line.Length - 10);
26                                     break;
27                                 }
28                             }
29                             //将读取到的歌词时间存放到数组中
30                             for (int i = 0; i < 500; i++)
31                             {
32                                 if (lrc[1, i] == null)
33                                 {
34                                     lrc[1, i] = line.Substring(1, 5);
35                                     break;
36                                 }
37                             }
38                         }
39                         /***********动态显示歌词***************/
40                         //获取播放器当前进度
41                         string numss = this.axWindowsMediaPlayer2.Ctlcontrols.currentPositionString;
42                         for (int i = 0; i < 500; i++)
43                         {
44                             if (lrc[1, i].Equals(numss))
45                             {
46                                 this.lblLrc.Text = lrc[0, i];
47                             }
48                             //else
49                             //{
50                             //    this.lblLrc.Text = "************";
51                             //}
52                         }
53                     }
54                 }
55                 catch (Exception ex)
56                 {
57                     //MessageBox.Show("异常:" + ex.Message);
58                 }
59             }
60         }
61         /// <summary>
62         /// 刷新歌词
63         /// </summary>
64         /// <param name="sender"></param>
65         /// <param name="e"></param>
66         private void timer5_Tick(object sender, EventArgs e)
67         {
68             ShowLrc();
69         }
70         #endregion
复制代码

 

 

ps.大家有好的建议欢迎提出:)

<think>嗯,用户问的是在C# WinForms中,窗体完全加载后调用方法。首先,我得回想一下WinForms的生命周期事件。窗体加载完成后,通常会触发Load事件,但有时候Load事件可能并不是完全加载完成的时机,比如当窗体上的所有控件都加载完毕并且可见的时候。用户可能遇到了在Load事件中调用方法时,某些控件还没准备好,导致问题的情况。 那正确的做法是什么呢?我记得窗体首次显示时会触发Shown事件,这个事件是在Load事件之后,窗体可见之后触发的。这时候应该所有的控件都已经初始化完成了。所以应该建议用户使用Shown事件来调用他们的方法。或者在窗体的构造函数中,将方法绑定到Shown事件上。 另外,用户可能不太清楚Load和Shown的区别,需要简单解释一下两者的触发时机,避免混淆。比如,Load事件是在窗体加载时触发,但此时可能控件的布局还没完全完成,而Shown是在窗体首次显示时触发,更合适执行需要所有控件就绪的操作。 还有,用户可能需要示例代码,所以应该给出具体的例子,比如在InitializeComponent之后订阅Shown事件,或者在属性窗口中找到Shown事件并添加处理方法。同时,提醒用户如果使用Load事件,可能需要调用Control.BeginInvoke来确保方法在UI线程完成绘制后执行,但这可能不如直接使用Shown事件可靠。 总结一下,关键点就是推荐使用Shown事件,解释其触发时机,并提供代码示例,同时对比Load事件的情况,帮助用户理解不同场景下的选择。另外,检查是否有其他可能的误解,比如多次触发的问题,但Shown事件只在第一次显示时触发,所以是安全的。</think>在 C# WinForms 中,若要在窗体**完全加载后调用方法**,通常可以通过窗体的 `Shown` 事件或 `Load` 事件实现。二者的主要区别在于触发时机: --- ### 1. **使用 `Shown` 事件(推荐)** - **触发时机**:窗体首次显示(`Visible = true`)后触发,此时所有控件已加载并完成布局。 - **优点**:确保窗体完全可见且控件已初始化,适合需要与用户交互或依赖控件渲染的逻辑。 - **实现步骤**: 1. 在设计器中双击窗体,自动生成 `Form_Shown` 事件。 2. 或在代码中手动绑定事件: ```csharp public Form1() { InitializeComponent(); this.Shown += Form1_Shown; // 在构造函数中绑定事件 } private void Form1_Shown(object sender, EventArgs e) { YourMethod(); // 窗体完全显示后执行 } private void YourMethod() { // 你的逻辑代码 } ``` --- ### 2. **使用 `Load` 事件** - **触发时机**:窗体加载时触发(在 `Shown` 之前),但此时控件可能尚未完成布局渲染。 - **适用场景**:初始化数据或控件属性,但若需操作依赖控件尺寸/位置,可能需要异步延迟执行。 - **示例代码**: ```csharp public Form1() { InitializeComponent(); this.Load += Form1_Load; } private void Form1_Load(object sender, EventArgs e) { // 直接调用(可能控件未完全渲染) YourMethod(); // 或者通过异步延迟确保渲染完成 this.BeginInvoke(new Action(() => YourMethod())); } ``` --- ### 关键区别总结 | 事件 | 触发时机 | 适用场景 | |---------|--------------------------|----------------------------| | `Load` | 窗体加载时(控件初始化后) | 初始化数据、非渲染依赖操作 | | `Shown` | 窗体首次显示后 | 需要控件完全渲染后的操作 | --- **建议**: - 如果方法依赖控件渲染(如获取控件尺寸、位置),优先使用 `Shown` 事件。 - 若需提前初始化数据,使用 `Load` 事件,但需注意可能的渲染延迟问题。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值