vod頁面上下頁循環

This commit is contained in:
allen.yan 2025-08-08 10:31:59 +08:00
parent f8a6e5c40d
commit 74740b1048

View File

@ -6,29 +6,30 @@ using System.Text;
namespace DualScreenDemo namespace DualScreenDemo
{ {
public partial class PrimaryForm : Form{ public partial class PrimaryForm : Form
{
public class MultiPagePanel : Panel public class MultiPagePanel : Panel
{ {
private const int ItemHeight = 70; private const int ItemHeight = 70;
private const int RowGap = 2; private const int RowGap = 2;
private int itemsPerPage private int itemsPerPage
{ {
get get
{ {
Screen screen = Screen.PrimaryScreen; Screen screen = Screen.PrimaryScreen;
int screenWidth = screen.Bounds.Width; int screenWidth = screen.Bounds.Width;
int screenHeight = screen.Bounds.Height; int screenHeight = screen.Bounds.Height;
if(screenWidth==1440 && screenHeight==900) if (screenWidth == 1440 && screenHeight == 900)
{ {
return 14; return 14;
} }
else if(screenWidth==1024 && screenHeight==768) else if (screenWidth == 1024 && screenHeight == 768)
{ {
return 12; return 12;
} }
else if(screenWidth == 1920 && screenHeight == 1080) else if (screenWidth == 1920 && screenHeight == 1080)
{ {
return 16; return 16;
} }
return 16; // 預設值 return 16; // 預設值
} }
@ -43,12 +44,12 @@ namespace DualScreenDemo
public bool IsSimplified public bool IsSimplified
{ {
get { return _isSimplified; } get { return _isSimplified; }
set set
{ {
if (_isSimplified != value) if (_isSimplified != value)
{ {
_isSimplified = value; _isSimplified = value;
if(currentArtistList != null && currentArtistList.Count > 0) if (currentArtistList != null && currentArtistList.Count > 0)
RefreshDisplayBase_Singer(); RefreshDisplayBase_Singer();
else else
RefreshDisplay(); RefreshDisplay();
@ -57,7 +58,8 @@ namespace DualScreenDemo
} }
private bool _isShowingSinger = true; private bool _isShowingSinger = true;
private List<SongData> currentSongList = new List<SongData>(); private List<SongData> currentSongList = new List<SongData>();
public List<SongData> get_currentSongList(){ public List<SongData> get_currentSongList()
{
return currentSongList; return currentSongList;
} }
private List<Artist> currentArtistList = new List<Artist>(); private List<Artist> currentArtistList = new List<Artist>();
@ -68,30 +70,30 @@ namespace DualScreenDemo
public int currentPageIndex public int currentPageIndex
{ {
get { return _currentPageIndex; } get { return _currentPageIndex; }
set set
{ {
if (_currentPageIndex != value) if (_currentPageIndex != value)
{ {
_currentPageIndex = value; _currentPageIndex = value;
// 觸發事件,通知頁面索引已改變 // 觸發事件,通知頁面索引已改變
PageIndexChanged?.Invoke(); PageIndexChanged?.Invoke();
} }
} }
} }
public int totalPages public int totalPages
{ {
get { return _totalPages; } get { return _totalPages; }
set set
{ {
if (_totalPages != value) if (_totalPages != value)
{ {
_totalPages = value; _totalPages = value;
// 觸發事件,通知頁面索引已改變 // 觸發事件,通知頁面索引已改變
PageIndexChanged?.Invoke(); PageIndexChanged?.Invoke();
} }
} }
} }
public MultiPagePanel() public MultiPagePanel()
{ {
this.SetStyle( this.SetStyle(
@ -102,7 +104,7 @@ namespace DualScreenDemo
true); true);
this.BackColor = Color.FromArgb(64, 0, 0, 0); this.BackColor = Color.FromArgb(64, 0, 0, 0);
this.BorderStyle = BorderStyle.None; this.BorderStyle = BorderStyle.None;
// 添加滑動事件 // 添加滑動事件
this.MouseDown += MultiPagePanel_MouseDown; this.MouseDown += MultiPagePanel_MouseDown;
this.MouseMove += MultiPagePanel_MouseMove; this.MouseMove += MultiPagePanel_MouseMove;
@ -125,12 +127,12 @@ namespace DualScreenDemo
int deltaX = e.X - mouseDownLocation.X; int deltaX = e.X - mouseDownLocation.X;
if (Math.Abs(deltaX) > 20) // 滑動距離超過50像素才觸發 if (Math.Abs(deltaX) > 20) // 滑動距離超過50像素才觸發
{ {
if (deltaX > 0 && currentPageIndex > 0) if (deltaX > 0 )
{ {
// 向右滑動,上一頁 // 向右滑動,上一頁
LoadPreviousPage(); LoadPreviousPage();
} }
else if (deltaX < 0 && currentPageIndex < totalPages - 1) else if (deltaX < 0)
{ {
// 向左滑動,下一頁 // 向左滑動,下一頁
LoadNextPage(); LoadNextPage();
@ -149,7 +151,7 @@ namespace DualScreenDemo
{ {
currentPageIndex++; currentPageIndex++;
// 如果歌單為0(沒有歌單),則刷新歌手列表 // 如果歌單為0(沒有歌單),則刷新歌手列表
if(_isShowingSinger) if (_isShowingSinger)
{ {
RefreshDisplayBase_Singer(); RefreshDisplayBase_Singer();
} }
@ -158,21 +160,41 @@ namespace DualScreenDemo
RefreshDisplay(); RefreshDisplay();
} }
} }
else
{
if (totalPages > 1)
{
currentPageIndex = -1;
LoadNextPage();
}
}
} }
public void LoadPreviousPage() public void LoadPreviousPage()
{ {
if (currentPageIndex - 1 >= 0) if (currentPageIndex - 1 >= 0)
{ {
currentPageIndex--; currentPageIndex--;
if(_isShowingSinger) if (_isShowingSinger)
{ {
RefreshDisplayBase_Singer(); RefreshDisplayBase_Singer();
} }
else else
{ {
RefreshDisplay(); RefreshDisplay();
} }
} }
else
{
if (totalPages > 1)
{
currentPageIndex = totalPages;
LoadPreviousPage();
}
}
} }
public void LoadSongs(List<SongData> songs, bool clearHistory = false) public void LoadSongs(List<SongData> songs, bool clearHistory = false)
@ -182,7 +204,7 @@ namespace DualScreenDemo
currentArtistList.Clear(); currentArtistList.Clear();
currentPageIndex = 0; currentPageIndex = 0;
totalPages = (int)Math.Ceiling(songs.Count / (double)itemsPerPage); totalPages = (int)Math.Ceiling(songs.Count / (double)itemsPerPage);
// 直接調用基礎刷新邏輯 // 直接調用基礎刷新邏輯
RefreshDisplayBase(); RefreshDisplayBase();
} }
@ -204,7 +226,7 @@ namespace DualScreenDemo
currentArtistList.Clear(); currentArtistList.Clear();
currentPageIndex = 0; currentPageIndex = 0;
totalPages = (int)Math.Ceiling(songs.Count / (double)itemsPerPage); totalPages = (int)Math.Ceiling(songs.Count / (double)itemsPerPage);
// 直接調用基礎刷新邏輯 // 直接調用基礎刷新邏輯
RefreshDisplayBase(); RefreshDisplayBase();
} }
@ -225,10 +247,10 @@ namespace DualScreenDemo
} }
this.SuspendLayout(); // 暫停 UI 更新,提高效能 this.SuspendLayout(); // 暫停 UI 更新,提高效能
this.Controls.Clear(); // 清空 UI (這裡會再清除一次) this.Controls.Clear(); // 清空 UI (這裡會再清除一次)
int startIndex = currentPageIndex * itemsPerPage; int startIndex = currentPageIndex * itemsPerPage;
int endIndex = Math.Min(startIndex + itemsPerPage, currentSongList.Count); int endIndex = Math.Min(startIndex + itemsPerPage, currentSongList.Count);
for (int i = startIndex; i < endIndex; i++) for (int i = startIndex; i < endIndex; i++)
{ {
CreateSongLabel(currentSongList[i], i - startIndex, startIndex); // 這行負責新增 UI CreateSongLabel(currentSongList[i], i - startIndex, startIndex); // 這行負責新增 UI
@ -237,7 +259,7 @@ namespace DualScreenDemo
} }
private void RefreshDisplayBase_Singer() private void RefreshDisplayBase_Singer()
{ {
this.Controls.Clear(); this.Controls.Clear();
if (this.InvokeRequired) // 確保 UI 操作在主執行緒執行 if (this.InvokeRequired) // 確保 UI 操作在主執行緒執行
{ {
this.Invoke(new Action(() => RefreshDisplayBase_Singer())); this.Invoke(new Action(() => RefreshDisplayBase_Singer()));
@ -245,30 +267,30 @@ namespace DualScreenDemo
} }
this.SuspendLayout(); // 暫停 UI 更新,提高效能 this.SuspendLayout(); // 暫停 UI 更新,提高效能
this.Controls.Clear(); // 清空 UI (這裡會再清除一次) this.Controls.Clear(); // 清空 UI (這裡會再清除一次)
int startIndex = currentPageIndex * itemsPerPage; int startIndex = currentPageIndex * itemsPerPage;
int endIndex = Math.Min(startIndex + itemsPerPage, currentArtistList.Count); int endIndex = Math.Min(startIndex + itemsPerPage, currentArtistList.Count);
for (int i = startIndex; i < endIndex; i++) for (int i = startIndex; i < endIndex; i++)
{ {
CreateSingerLabel(currentArtistList[i], i - startIndex, startIndex); // 這行負責新增 UI CreateSingerLabel(currentArtistList[i], i - startIndex, startIndex); // 這行負責新增 UI
} }
this.ResumeLayout(); // 恢復 UI 更新 this.ResumeLayout(); // 恢復 UI 更新
this.Invalidate(); this.Invalidate();
} }
private void CreateSingerLabel(Artist artist, int index, int pageOffset) private void CreateSingerLabel(Artist artist, int index, int pageOffset)
{ {
// 創建歌手標籤 // 創建歌手標籤
Label artistLabel = new Label(); Label artistLabel = new Label();
string artistText = IsSimplified ? string artistText = IsSimplified ?
(!string.IsNullOrEmpty(artist.NameSimplified) ? artist.NameSimplified : artist.Name) : (!string.IsNullOrEmpty(artist.NameSimplified) ? artist.NameSimplified : artist.Name) :
artist.Name; artist.Name;
artistLabel.Text = artistText; artistLabel.Text = artistText;
artistLabel.Tag = artist; artistLabel.Tag = artist;
artistLabel.AutoSize = true; artistLabel.AutoSize = true;
// 計算文字寬度 // 計算文字寬度
artistLabel.Font = new Font("微軟正黑體", 22, FontStyle.Bold); artistLabel.Font = new Font("微軟正黑體", 22, FontStyle.Bold);
Screen screen = Screen.PrimaryScreen; Screen screen = Screen.PrimaryScreen;
@ -282,22 +304,22 @@ namespace DualScreenDemo
_ => 8 // 預設值 _ => 8 // 預設值
}; };
// 計算位置 - 依照NumberOfItem來計算 // 計算位置 - 依照NumberOfItem來計算
bool isLeftColumn = index < NumberOfItem; bool isLeftColumn = index < NumberOfItem;
int row = isLeftColumn ? index : index - NumberOfItem; // 如果是右边,需要减去8来计算正确的行号 int row = isLeftColumn ? index : index - NumberOfItem; // 如果是右边,需要减去8来计算正确的行号
float startX = isLeftColumn ? LeftColumnX : RightColumnX; float startX = isLeftColumn ? LeftColumnX : RightColumnX;
int y = row * (ItemHeight + RowGap); int y = row * (ItemHeight + RowGap);
// 計算歌手標籤的位置和大小 // 計算歌手標籤的位置和大小
int singerX = (int)(this.Width * startX); int singerX = (int)(this.Width * startX);
int singerWidth = (int)(this.Width * (SongWidth+ArtistWidth)); int singerWidth = (int)(this.Width * (SongWidth + ArtistWidth));
// 字體顏色 // 字體顏色
artistLabel.ForeColor = Color.White; artistLabel.ForeColor = Color.White;
// 標籤座標設定 // 標籤座標設定
artistLabel.Location = new Point(singerX, y); artistLabel.Location = new Point(singerX, y);
artistLabel.Size = new Size(singerWidth + 20, ItemHeight); artistLabel.Size = new Size(singerWidth + 20, ItemHeight);
Panel separatorPanel = new Panel Panel separatorPanel = new Panel
{ {
Location = new Point(singerX , y + ItemHeight), Location = new Point(singerX, y + ItemHeight),
//Size = new Size(singerWidth + 20, 2), //Size = new Size(singerWidth + 20, 2),
Size = new Size(730, 2), Size = new Size(730, 2),
BackColor = Color.FromArgb(80, 255, 255, 255), BackColor = Color.FromArgb(80, 255, 255, 255),
@ -306,28 +328,30 @@ namespace DualScreenDemo
// 字體調整和字體背景顏色 // 字體調整和字體背景顏色
artistLabel.TextAlign = ContentAlignment.TopLeft; artistLabel.TextAlign = ContentAlignment.TopLeft;
artistLabel.BackColor = Color.Transparent; artistLabel.BackColor = Color.Transparent;
// 設置滑鼠事件 // 設置滑鼠事件
EventHandler mouseEnter = (sender, e) => { EventHandler mouseEnter = (sender, e) =>
// 變更歌手名稱為黃色 {
artistLabel.ForeColor = Color.Yellow; // 變更歌手名稱為黃色
// 增強分隔線的亮度,使其更明顯 artistLabel.ForeColor = Color.Yellow;
separatorPanel.BackColor = Color.FromArgb(120, 255, 255, 255); // 增強分隔線的亮度,使其更明顯
separatorPanel.BackColor = Color.FromArgb(120, 255, 255, 255);
}; };
EventHandler mouseLeave = (sender, e) => { EventHandler mouseLeave = (sender, e) =>
// 還原歌手名稱為白色 {
artistLabel.ForeColor = Color.White; // 還原歌手名稱為白色
// 還原分隔線的亮度 artistLabel.ForeColor = Color.White;
separatorPanel.BackColor = Color.FromArgb(80, 255, 255, 255); // 還原分隔線的亮度
separatorPanel.BackColor = Color.FromArgb(80, 255, 255, 255);
}; };
artistLabel.Click += (sender, e) => artistLabel.Click += (sender, e) =>
{ {
string searchText = artistLabel.Text; // 取得輸入內容 string searchText = artistLabel.Text; // 取得輸入內容
// 歌星 轉 歌曲 // 歌星 轉 歌曲
string query = IsSimplified ? string query = IsSimplified ?
( (
!string.IsNullOrEmpty(artist.NameSimplified)? !string.IsNullOrEmpty(artist.NameSimplified) ?
$"SELECT * FROM song_library_cache WHERE artistA_simplified = '{searchText}' OR artistB_simplified = '{searchText}'" $"SELECT * FROM song_library_cache WHERE artistA_simplified = '{searchText}' OR artistB_simplified = '{searchText}'"
: $"SELECT * FROM song_library_cache WHERE artistA = '{searchText}' OR artistB = '{searchText}'" : $"SELECT * FROM song_library_cache WHERE artistA = '{searchText}' OR artistB = '{searchText}'"
) )
@ -357,7 +381,7 @@ namespace DualScreenDemo
this.Controls.Add(artistLabel); this.Controls.Add(artistLabel);
// 將歌手標籤置於最上層 // 將歌手標籤置於最上層
artistLabel.BringToFront(); artistLabel.BringToFront();
} }
private void CreateSongLabel(SongData song, int index, int pageOffset) private void CreateSongLabel(SongData song, int index, int pageOffset)
@ -386,7 +410,7 @@ namespace DualScreenDemo
string fullText = songText + statusText; string fullText = songText + statusText;
int textLength = fullText.Length; int textLength = fullText.Length;
// 計算文字寬度 // 計算文字寬度
songLabel.Font = new Font("微軟正黑體", 22, FontStyle.Bold); songLabel.Font = new Font("微軟正黑體", 22, FontStyle.Bold);
songLabel.Text = fullText; songLabel.Text = fullText;
@ -402,21 +426,21 @@ namespace DualScreenDemo
int screenWidth = screen.Bounds.Width; int screenWidth = screen.Bounds.Width;
int screenHeight = screen.Bounds.Height; int screenHeight = screen.Bounds.Height;
int NumberOfItem = 0; int NumberOfItem = 0;
if(screenWidth==1440 && screenHeight==900) if (screenWidth == 1440 && screenHeight == 900)
{ {
NumberOfItem = 7; NumberOfItem = 7;
} }
else if(screenWidth==1024 && screenHeight==768) else if (screenWidth == 1024 && screenHeight == 768)
{ {
NumberOfItem = 6; NumberOfItem = 6;
} }
else if(screenWidth == 1920 && screenHeight == 1080) else if (screenWidth == 1920 && screenHeight == 1080)
{ {
NumberOfItem = 8; NumberOfItem = 8;
} }
// 計算位置 - 依照NumberOfItem來計算 // 計算位置 - 依照NumberOfItem來計算
bool isLeftColumn = index < NumberOfItem; bool isLeftColumn = index < NumberOfItem;
int row = isLeftColumn ? index : index - NumberOfItem; int row = isLeftColumn ? index : index - NumberOfItem;
float startX = isLeftColumn ? LeftColumnX : RightColumnX; float startX = isLeftColumn ? LeftColumnX : RightColumnX;
int y = row * (ItemHeight + RowGap); int y = row * (ItemHeight + RowGap);
// 設置位置和大小 // 設置位置和大小
@ -439,7 +463,7 @@ namespace DualScreenDemo
}; };
this.Controls.Add(icon); this.Controls.Add(icon);
icon.BringToFront(); icon.BringToFront();
// 有圖標時歌名右移 // 有圖標時歌名右移
songLabel.Location = new Point(songX + 42, y); songLabel.Location = new Point(songX + 42, y);
//songLabel.Size = new Size(songWidth - 47, ItemHeight - 20); //songLabel.Size = new Size(songWidth - 47, ItemHeight - 20);
@ -455,18 +479,20 @@ namespace DualScreenDemo
// 歌手標籤位置調整 // 歌手標籤位置調整
artistLabel.Location = new Point(artistX, y + 33); artistLabel.Location = new Point(artistX, y + 33);
artistLabel.Size = new Size(artistWidth - 10, ItemHeight - 35); artistLabel.Size = new Size(artistWidth - 10, ItemHeight - 35);
if (artistText.Length > 3)
{
artistLabel.Location = new Point(artistX - 95, y + 33);
artistLabel.Size = new Size(artistWidth + 90, ItemHeight - 35);
}
if (song.getB() != null) if (song.getB() != null)
{ {
artistText += " + " + song.getArtist_B(IsSimplified); artistText += " + " + song.getArtist_B(IsSimplified);
artistLabel.Location = new Point(artistX - 95, y + 33); //artistLabel.Location = new Point(artistX - 95, y + 33);
artistLabel.Size = new Size(artistWidth + 90, ItemHeight - 35); //artistLabel.Size = new Size(artistWidth + 90, ItemHeight - 35);
} }
if (artistText.Length > 3)
{
artistLabel.Location = new Point(artistX - 581, y + 33);
artistLabel.Size = new Size(artistWidth + 573, ItemHeight - 35);
}
artistLabel.Text = artistText; artistLabel.Text = artistText;
// 創建分隔線面板 // 創建分隔線面板
Panel separatorPanel = new Panel Panel separatorPanel = new Panel
@ -487,24 +513,26 @@ namespace DualScreenDemo
artistLabel.Font = new Font("微軟正黑體", fold, FontStyle.Bold); artistLabel.Font = new Font("微軟正黑體", fold, FontStyle.Bold);
//artistLabel.ForeColor = Color.FromArgb(30,144,255); //artistLabel.ForeColor = Color.FromArgb(30,144,255);
artistLabel.ForeColor = Color.FromArgb(36,209,216); artistLabel.ForeColor = Color.FromArgb(36, 209, 216);
songLabel.TextAlign = ContentAlignment.MiddleLeft; songLabel.TextAlign = ContentAlignment.MiddleLeft;
artistLabel.TextAlign = ContentAlignment.MiddleRight; artistLabel.TextAlign = ContentAlignment.MiddleRight;
// 確保背景透明 // 確保背景透明
songLabel.BackColor = Color.Transparent; songLabel.BackColor = Color.Transparent;
artistLabel.BackColor = Color.Transparent; artistLabel.BackColor = Color.Transparent;
// 定義滑鼠進入 (MouseEnter) 事件的處理程序 // 定義滑鼠進入 (MouseEnter) 事件的處理程序
EventHandler mouseEnter = (sender, e) => { EventHandler mouseEnter = (sender, e) =>
{
songLabel.ForeColor = Color.Yellow; songLabel.ForeColor = Color.Yellow;
artistLabel.ForeColor = Color.Yellow; artistLabel.ForeColor = Color.Yellow;
separatorPanel.BackColor = Color.FromArgb(120, 255, 255, 255); separatorPanel.BackColor = Color.FromArgb(120, 255, 255, 255);
}; };
// 定義滑鼠離開 (MouseLeave) 事件的處理程序 // 定義滑鼠離開 (MouseLeave) 事件的處理程序
EventHandler mouseLeave = (sender, e) => { EventHandler mouseLeave = (sender, e) =>
{
songLabel.ForeColor = color; songLabel.ForeColor = color;
//artistLabel.ForeColor = Color.FromArgb(30, 144, 255); //artistLabel.ForeColor = Color.FromArgb(30, 144, 255);
artistLabel.ForeColor = Color.FromArgb(36,209,216); artistLabel.ForeColor = Color.FromArgb(36, 209, 216);
separatorPanel.BackColor = Color.FromArgb(80, 255, 255, 255); separatorPanel.BackColor = Color.FromArgb(80, 255, 255, 255);
}; };
// 添加事件处理 // 添加事件处理