C#_音樂播放器_用ListBox顯示歌詞
阿新 • • 發佈:2019-02-06
在用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>
至此,整個歌詞的自動繪製就基本上完成了,顯示效果除了當前行是用紅色一次性顯示完成意外,其餘的滾動和酷狗音樂中歌詞寫真基本上是一樣的。