1. 程式人生 > >C#_音樂播放器_用ListBox顯示歌詞

C#_音樂播放器_用ListBox顯示歌詞

  在用ListBox顯示歌詞的時候,可以顯示多行,同時可以控制每一行顯示的樣式等等。控制顯示樣式是在它的DrawItem事件中來控制的。首先要先將ListBox的DrawMode屬性設定為OwnerDrawVariable或OwnerDrawFixed。ListBox有個ItemHeight屬性,在DrawMode設定為Normal時,這個屬性是不可設定的,並且其值是根據當前字型進行計算獲得的。只有當DrawMode設定為OwnerDrawVariable或OwnerDrawFixed時,設定ItemHeight才生效。DrawMode屬性中有三個成員變數:

屬性值 說明
Normal 元件裡面的所有元素都是作業系統來繪製,並且所有元件大小相同。(預設值)
OwnerDrawFixed 元件裡面的所有元素都是由我們手動繪製,並且大小相同
OwnerDrawVariable 元件裡面的所有元素都是由我們手動繪製,大小可以不相同

DrawItem事件中,的引數e裡面有許多的屬性值,包括獲取前景色和背景色,獲取當前繪製行(焦點行)從0開始的索引,獲取字型、畫筆、範圍、狀態等等很多的內容。這次試用的是索引,字型,畫筆和範圍。

在定時器中先為ListBox要顯示的歌詞進行賦值,程式碼如下:

<span style="font-size:18px;">private void timer1_Tick(object sender, EventArgs e)
{	
	//也幾行可以寫在定時器外面
	int totalHeight = listShowSongLrc.Height;
	//設定顯示的每一項的高度
	int height = listShowSongLrc.ItemHeight = 30;
	//需要顯示多少行歌詞
	int num = totalHeight / height;
	//顯示歌詞為奇數行,方便獲取當前歌詞行
	num = num%2==1?num:num-1;
	
	if (songLrc != null)
	{
		#region MyRegion
		for (int i = 0; i < songLrc.Length - 1; i++)
		{
		   //歌曲當前位置
			string currenPosition = axMediaPlayer.Ctlcontrols.currentPositionString;
			
			//歌曲唱的過程中,顯示當前歌詞的前後各num/2行
			if (CheckTime(currenPosition, songLrc[i]) && CheckTime(songLrc[i + 1], currenPosition))
			{
				//清除只能夠放在if裡面,放在if外面基本上看不到歌詞
				listShowSongLrc.Items.Clear();

				for (int x = (i - num / 2); x <= (i + num / 2); x++)
				{
					listShowSongLrc.Items.Add(x < 0 || x >= songLrc.Length ? "" : GetSongLrc(x));
				}
			}
			//歌曲唱完以後,後面顯示為空
			if (CheckTime(currenPosition, songLrc[songLrc.Length - 1]))
			{
				listShowSongLrc.Items.Clear();
				for (int x = -num / 2; x <= num / 2; x++)
				{
					listShowSongLrc.Items.Add(x <= 0 ? GetSongLrc(songLrc.Length - 1 + x) : "");
				}
			}
			//歌詞還沒有開始顯示的時候,中間顯示歌名,後面顯示前幾行歌詞
			if (CheckTime(songLrc[0], currenPosition))
			{
				listShowSongLrc.Items.Clear();
				for (int x = -num / 2; x <= num / 2; x++)
				{
					listShowSongLrc.Items.Add(x > 0 ? GetSongLrc(x) : (x < 0 ? "" : listShowSong.Items[listSong.IndexOf(axMediaPlayer.URL)]));
				}
			}
			//讓每一項獲得焦點,呼叫歌詞繪製事件DrawItem
			for (int j = 0; j < listShowSongLrc.Items.Count; j++)
			{
				listShowSongLrc.SelectedIndex = j;
			}
		}
		#endregion
	}
	else
	{
		listShowSongLrc.Items.Clear();
		for (int x = 0; x < num; x++)
		{                       
			listShowSongLrc.Items.Add(x != num / 2 ? "" : "---未  找  到  歌  詞---");
		}
	}
}</span>

上面涉及到兩個方法,比較當前時間和歌詞的時間大小方法。歌詞中,是按照時間來進行一個排序的,每一行歌詞前面是時間,然後用’|‘和歌詞分割,可以百度下一首歌詞(.lrc)來看看
<span style="font-size:18px;">        private bool CheckTime(string str1, string str2)
        {
            return string.CompareOrdinal(str1, 0, str2, 0, str2.Length) > 0;
        }</span>

獲取當前時間的歌詞方法

,歌詞是存放在一個數組中,傳遞過來當前要獲取的行數,進行歌詞的分割,然後返回

<span style="font-size:18px;"> private string GetSongLrc(int i)
        {
            return songLrc[i].Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries)[1];
        }</span>

接下來便是ListBox中歌詞的繪製,是通過畫圖的方式來實現的(GDI+)

<span style="font-size:18px;">private void listShowSongLrc_DrawItem(object sender, DrawItemEventArgs e)
{
	//獲取當前繪製的行的索引
	int index = e.Index;
	Graphics g = e.Graphics;
	//得到每一項的繪製區域大小
	Rectangle bound = e.Bounds;
	//得到當前項的文字內容
	string text = listShowSongLrc.Items[index].ToString();
	
	//判斷當前選擇的項是正在唱的歌詞,也就是中間一行歌詞
	if (index == listShowSongLrc.Items.Count / 2)
	{//如果當前行為選中行。
		//繪製選中時要顯示的藍色邊框,實際不需要就註釋掉了
		// g.DrawRectangle(Pens.Blue, bound.Left, bound.Top, bound.Width - 1, bound.Height - 1);
		//繪製邊框後,裡面的矩形框大小改變,故重新定義一個,如果沒有繪製邊框就不需要重新定義
		Rectangle rect = new Rectangle(bound.Left - 1, bound.Top - 1,
									   bound.Width - 2, bound.Height - 2);
		//繪製選中時要顯示的藍色背景。可以選中其它色,此處省略了背景繪製
		// g.FillRectangle(Brushes.Blue, rect);
		//定義一個字型,是用來繪製顯示的當前歌詞文字。
		Font font = new System.Drawing.Font("微軟雅黑", 18, FontStyle.Bold & FontStyle.Italic);
		//繪製歌詞,顏色為紅色
		TextRenderer.DrawText(g, text, font, rect, Color.Red,
							  TextFormatFlags.VerticalCenter);
	}
	else
	{   
		//定義一個顏色為白色的畫刷
		using (Brush brush = new SolidBrush(Color.White))
		{
			g.FillRectangle(brush, bound);//繪製背景色。
		}
		//填充字型,字型的顏色為黑色
		TextRenderer.DrawText(g, text, this.Font, bound, Color.Black,
							  TextFormatFlags.VerticalCenter | TextFormatFlags.Left);
	}
}</span>

至此,整個歌詞的自動繪製就基本上完成了,顯示效果除了當前行是用紅色一次性顯示完成意外,其餘的滾動和酷狗音樂中歌詞寫真基本上是一樣的。