using DBObj; using System.IO; namespace DualScreenDemo { public partial class PrimaryForm : Form{ public class MultiPagePanel : Panel { private const int ItemHeight = 70; private const int RowGap = 2; private int itemsPerPage { get { Screen screen = Screen.PrimaryScreen; int screenWidth = screen.Bounds.Width; int screenHeight = screen.Bounds.Height; if(screenWidth==1440 && screenHeight==900) { return 14; } else if(screenWidth==1024 && screenHeight==768) { return 12; } else if(screenWidth == 1920 && screenHeight == 1080) { return 16; } return 16; // 預設值 } } private const float LeftColumnX = 0.03f; private const float RightColumnX = 0.52f; private const float SongWidth = 0.35f; private const float ArtistWidth = 0.12f; private int _currentPageIndex = 0; private bool _isSimplified = false; public bool IsSimplified { get { return _isSimplified; } set { if (_isSimplified != value) { _isSimplified = value; if(currentArtistList != null && currentArtistList.Count > 0) RefreshDisplayBase_Singer(); else RefreshDisplay(); } } } private bool _isShowingSinger = true; private List currentSongList = new List(); public List get_currentSongList(){ return currentSongList; } private List currentArtistList = new List(); private int _totalPages = 0; private Point mouseDownLocation; // 新增字段 private bool isDragging = false; // 新增字段 public event Action PageIndexChanged; // 新增事件 public int currentPageIndex { get { return _currentPageIndex; } set { if (_currentPageIndex != value) { _currentPageIndex = value; // 觸發事件,通知頁面索引已改變 PageIndexChanged?.Invoke(); } } } public int totalPages { get { return _totalPages; } set { if (_totalPages != value) { _totalPages = value; // 觸發事件,通知頁面索引已改變 PageIndexChanged?.Invoke(); } } } public MultiPagePanel() { this.SetStyle( ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.ResizeRedraw, true); this.BackColor = Color.FromArgb(64, 0, 0, 0); this.BorderStyle = BorderStyle.None; // 添加滑動事件 this.MouseDown += MultiPagePanel_MouseDown; this.MouseMove += MultiPagePanel_MouseMove; this.MouseUp += MultiPagePanel_MouseUp; } private void MultiPagePanel_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { mouseDownLocation = e.Location; isDragging = true; } } private void MultiPagePanel_MouseMove(object sender, MouseEventArgs e) { if (isDragging) { int deltaX = e.X - mouseDownLocation.X; if (Math.Abs(deltaX) > 20) // 滑動距離超過50像素才觸發 { if (deltaX > 0 && currentPageIndex > 0) { // 向右滑動,上一頁 LoadPreviousPage(); } else if (deltaX < 0 && currentPageIndex < totalPages - 1) { // 向左滑動,下一頁 LoadNextPage(); } isDragging = false; } } } private void MultiPagePanel_MouseUp(object sender, MouseEventArgs e) { isDragging = false; } public void LoadNextPage() { if (currentPageIndex < totalPages - 1) { currentPageIndex++; // 如果歌單為0(沒有歌單),則刷新歌手列表 if(_isShowingSinger) { RefreshDisplayBase_Singer(); } else { RefreshDisplay(); } } } public void LoadPreviousPage() { if (currentPageIndex - 1 >= 0) { currentPageIndex--; if(_isShowingSinger) { RefreshDisplayBase_Singer(); } else { RefreshDisplay(); } } } public void LoadSongs(List songs, bool clearHistory = false) { _isShowingSinger = false; currentSongList = songs; currentArtistList.Clear(); currentPageIndex = 0; totalPages = (int)Math.Ceiling(songs.Count / (double)itemsPerPage); // 直接調用基礎刷新邏輯 RefreshDisplayBase(); } public void LoadSingers(List artists) { _isShowingSinger = true; currentArtistList = artists; // currentSongList.Clear(); currentPageIndex = 0; totalPages = (int)Math.Ceiling(artists.Count / (double)itemsPerPage); RefreshDisplayBase_Singer(); } public void LoadPlayedSongs(List songs, List states) { _isShowingSinger = false; currentSongList = songs; currentArtistList.Clear(); currentPageIndex = 0; totalPages = (int)Math.Ceiling(songs.Count / (double)itemsPerPage); // 直接調用基礎刷新邏輯 RefreshDisplayBase(); } public void RefreshDisplay() { this.Controls.Clear(); // 清除所有 UI 元件 RefreshDisplayBase(); // 重新建立 UI this.Invalidate(); // 通知系統需要重新繪製 } private void RefreshDisplayBase() { if (this.InvokeRequired) // 確保 UI 操作在主執行緒執行 { this.Invoke(new Action(() => RefreshDisplayBase())); return; } this.SuspendLayout(); // 暫停 UI 更新,提高效能 this.Controls.Clear(); // 清空 UI (這裡會再清除一次) int startIndex = currentPageIndex * itemsPerPage; int endIndex = Math.Min(startIndex + itemsPerPage, currentSongList.Count); for (int i = startIndex; i < endIndex; i++) { CreateSongLabel(currentSongList[i], i - startIndex, startIndex); // 這行負責新增 UI } this.ResumeLayout(); // 恢復 UI 更新 } private void RefreshDisplayBase_Singer() { this.Controls.Clear(); if (this.InvokeRequired) // 確保 UI 操作在主執行緒執行 { this.Invoke(new Action(() => RefreshDisplayBase_Singer())); return; } this.SuspendLayout(); // 暫停 UI 更新,提高效能 this.Controls.Clear(); // 清空 UI (這裡會再清除一次) int startIndex = currentPageIndex * itemsPerPage; int endIndex = Math.Min(startIndex + itemsPerPage, currentArtistList.Count); for (int i = startIndex; i < endIndex; i++) { CreateSingerLabel(currentArtistList[i], i - startIndex, startIndex); // 這行負責新增 UI } this.ResumeLayout(); // 恢復 UI 更新 this.Invalidate(); } private void CreateSingerLabel(Artist artist, int index, int pageOffset) { // 創建歌手標籤 Label artistLabel = new Label(); string artistText = IsSimplified ? (!string.IsNullOrEmpty(artist.NameSimplified) ? artist.NameSimplified : artist.Name) : artist.Name; artistLabel.Text = artistText; artistLabel.Tag = artist; artistLabel.AutoSize = false; // 計算文字寬度 Font normalFont = new Font("微軟正黑體", 24, FontStyle.Bold); Font mediumFont = new Font("微軟正黑體", 18, FontStyle.Bold); Font smallFont = new Font("微軟正黑體", 14, FontStyle.Bold); // 根據文字長度設置字體大小 if (artistLabel.Text.Length > 18) { artistLabel.Font = smallFont; } else if (artistLabel.Text.Length > 13) { artistLabel.Font = mediumFont; } else { artistLabel.Font = normalFont; } Screen screen = Screen.PrimaryScreen; int screenWidth = screen.Bounds.Width; int screenHeight = screen.Bounds.Height; int NumberOfItem = (screenWidth, screenHeight) switch { (1440, 900) => 7, (1024, 768) => 6, (1920, 1080) => 8, _ => 8 // 預設值 }; // 計算位置 - 依照NumberOfItem來計算 bool isLeftColumn = index < NumberOfItem; int row = isLeftColumn ? index : index - NumberOfItem; // 如果是右边,需要减去8来计算正确的行号 float startX = isLeftColumn ? LeftColumnX : RightColumnX; int y = row * (ItemHeight + RowGap); // 計算歌手標籤的位置和大小 int singerX = (int)(this.Width * startX); int singerWidth = (int)(this.Width * (SongWidth+ArtistWidth)); // 字體顏色 artistLabel.ForeColor = Color.White; // 標籤座標設定 artistLabel.Location = new Point(singerX, y); artistLabel.Size = new Size(singerWidth + 20, ItemHeight); Panel separatorPanel = new Panel { Location = new Point(singerX , y + ItemHeight), Size = new Size(singerWidth + 20, 2), BackColor = Color.FromArgb(80, 255, 255, 255), Name = "SeparatorPanel_" + index.ToString() }; // 字體調整和字體背景顏色 artistLabel.TextAlign = ContentAlignment.TopLeft; artistLabel.BackColor = Color.Transparent; // 設置滑鼠事件 EventHandler mouseEnter = (sender, e) => { // 變更歌手名稱為黃色 artistLabel.ForeColor = Color.Yellow; // 增強分隔線的亮度,使其更明顯 separatorPanel.BackColor = Color.FromArgb(120, 255, 255, 255); }; EventHandler mouseLeave = (sender, e) => { // 還原歌手名稱為白色 artistLabel.ForeColor = Color.White; // 還原分隔線的亮度 separatorPanel.BackColor = Color.FromArgb(80, 255, 255, 255); }; artistLabel.Click += (sender, e) => { string searchText = artistLabel.Text; // 取得輸入內容 // 歌星 轉 歌曲 string query = IsSimplified ? ( !string.IsNullOrEmpty(artist.NameSimplified)? $"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}'" ; //string query = $"SELECT * FROM song_library_cache WHERE artistA ='{searchText}' OR artistB='{searchText}' "; var searchResults = PrimaryForm.Instance.SearchSongs_Mysql(query); // 重置分頁 PrimaryForm.Instance.currentPage = 0; currentSongList = searchResults; totalPages = (int)Math.Ceiling((double)searchResults.Count / itemsPerPage); // 更新多頁面面板的內容 PrimaryForm.Instance.multiPagePanel.currentPageIndex = 0; PrimaryForm.Instance.multiPagePanel.LoadSongs(currentSongList); }; // 添加滑鼠事件 artistLabel.MouseEnter += mouseEnter; artistLabel.MouseLeave += mouseLeave; // 滑動 artistLabel.MouseDown += MultiPagePanel_MouseDown; artistLabel.MouseMove += MultiPagePanel_MouseMove; artistLabel.MouseUp += MultiPagePanel_MouseUp; separatorPanel.MouseEnter += mouseEnter; separatorPanel.MouseLeave += mouseLeave; // 添加到畫面上 this.Controls.Add(separatorPanel); this.Controls.Add(artistLabel); // 將歌手標籤置於最上層 artistLabel.BringToFront(); } private void CreateSongLabel(SongData song, int index, int pageOffset) { // 創建歌曲標籤 Label songLabel = new Label(); string statusText = ""; // 狀態文字 bool isCurrentlyPlaying = false; // 是否正在播放 bool hasBeenPlayed = false; // 是否已播放完成 bool isLatestInstance = true; // 是否是最新的歌曲 // 僅在 "已點歌曲" 頁面顯示播放狀態 if (PrimaryForm.Instance.isOnOrderedSongsPage) { // 判斷是否正在播放公播歌單 (若用戶點播歌單為空,則播放公播歌單) bool isPlayingPublicList = userRequestedSongs.Count == 0 || (currentSongIndexInHistory >= userRequestedSongs.Count - 1 && PrimaryForm.Instance.videoPlayerForm.IsPlayingPublicSong); if (isPlayingPublicList) { // 若播放公播歌單,代表已點歌曲皆已播放完畢 hasBeenPlayed = true; songLabel.ForeColor = Color.Gray; statusText = IsSimplified ? "(播毕)" : "(播畢)"; } else { // 計算已完成播放的歌曲數量 int completedCount = currentSongIndexInHistory; //Console.WriteLine("currentSongIndexInHistory:" + currentSongIndexInHistory); // 遍歷已點歌曲歷史 /*for (int i = 0; i <= currentSongIndexInHistory && i < playedSongsHistory.Count; i++) { if (i == currentSongIndexInHistory) { completedCount = i + 1; // 当前播放的歌曲 break; } // 检查播放状态 if (i < playStates.Count) { if (playStates[i] == PlayState.Played || playStates[i] == PlayState.Playing) { completedCount++; } // 如果是切歌状态,不增加计数 } }*/ // 計算歌曲在歷史中的位置 int songPosition = pageOffset + index; // 判斷歌曲狀態 if (songPosition < completedCount) { // 已播放完成 hasBeenPlayed = true; songLabel.ForeColor = Color.Gray; statusText = IsSimplified ? "(播毕)" : "(播畢)"; } else if (songPosition == completedCount) { // 正在播放 isCurrentlyPlaying = true; songLabel.ForeColor = Color.LimeGreen; statusText = IsSimplified ? "(播放中)" : "(播放中)"; } else { // 未播放 songLabel.ForeColor = Color.White; statusText = string.Empty; } } } else { // 未在 "已點歌曲" 頁面顯示白色 songLabel.ForeColor = Color.White; statusText = string.Empty; } // 根據簡繁體設置選擇要顯示的文字 string songText = song.getName(IsSimplified); // 歌手名稱設置點 string artistText = song.getArtist_A(IsSimplified); string fullText = songText + statusText; int textLength = fullText.Length; // 計算文字寬度 Font normalFont = new Font("微軟正黑體", 20, FontStyle.Bold); Font mediumFont = new Font("微軟正黑體", 14, FontStyle.Bold); Font smallFont = new Font("微軟正黑體", 12, FontStyle.Bold); // 根據文字長度設置字體大小 if (textLength > 18) { songLabel.Font = smallFont; } else if (textLength > 8) { songLabel.Font = mediumFont; } else { songLabel.Font = normalFont; } songLabel.Text = fullText; songLabel.Tag = song; songLabel.AutoSize = false; // 創建歌手標籤 Label artistLabel = new Label(); artistLabel.Text = artistText; artistLabel.Tag = song; artistLabel.AutoSize = false; Screen screen = Screen.PrimaryScreen; int screenWidth = screen.Bounds.Width; int screenHeight = screen.Bounds.Height; int NumberOfItem = 0; if(screenWidth==1440 && screenHeight==900) { NumberOfItem = 7; } else if(screenWidth==1024 && screenHeight==768) { NumberOfItem = 6; } else if(screenWidth == 1920 && screenHeight == 1080) { NumberOfItem = 8; } // 計算位置 - 依照NumberOfItem來計算 bool isLeftColumn = index < NumberOfItem; int row = isLeftColumn ? index : index - NumberOfItem; float startX = isLeftColumn ? LeftColumnX : RightColumnX; int y = row * (ItemHeight + RowGap); // 設置位置和大小 int songX = (int)(this.Width * startX); int songWidth = (int)(this.Width * SongWidth); int artistWidth = (int)(this.Width * ArtistWidth); int artistX = songX + songWidth + 10; // 添加人聲標籤 if (song.HumanVoice == 1) { PictureBox icon = new PictureBox() { Image = Image.FromFile(Path.Combine(Application.StartupPath, @"themes\superstar\其他符號_人聲\其他符號_人聲.png")), SizeMode = PictureBoxSizeMode.Zoom, Size = new Size(32, 32), Location = new Point(songX + 5, y + 8) }; this.Controls.Add(icon); icon.BringToFront(); // 有圖標時歌名右移 songLabel.Location = new Point(songX + 42, y); songLabel.Size = new Size(songWidth - 47, ItemHeight - 20); } else { // 沒有圖標時歌名置中 songLabel.Location = new Point(songX, y); songLabel.Size = new Size(songWidth - 10, ItemHeight - 20); } // 歌手標籤位置調整 artistLabel.Location = new Point(artistX, y + 33); artistLabel.Size = new Size(artistWidth - 10, ItemHeight - 35); // 創建分隔線面板 Panel separatorPanel = new Panel { Location = new Point(songX - 5, y + ItemHeight - 2), Size = new Size(songWidth + artistWidth + 20, 2), BackColor = Color.FromArgb(80, 255, 255, 255), Name = "SeparatorPanel_" + index.ToString() }; // 根據文字長度設置字體大小 if (artistText.Length > 6) { artistLabel.Font = new Font("微軟正黑體", 10, FontStyle.Bold); } else if (artistText.Length > 3) { artistLabel.Font = new Font("微軟正黑體", 12, FontStyle.Bold); } else { artistLabel.Font = new Font("微軟正黑體", 14, FontStyle.Bold); } //artistLabel.Font = new Font("微軟正黑體", 16, FontStyle.Bold); artistLabel.ForeColor = Color.FromArgb(30,144,255); songLabel.TextAlign = ContentAlignment.MiddleLeft; artistLabel.TextAlign = ContentAlignment.MiddleRight; // 確保背景透明 songLabel.BackColor = Color.Transparent; artistLabel.BackColor = Color.Transparent; // 定義滑鼠進入 (MouseEnter) 事件的處理程序 EventHandler mouseEnter = (sender, e) => { // 當不在「已點歌曲」頁面,或者該歌曲不是當前正在播放的歌曲, // 且(該歌曲未播放過或不是該歌曲的最新實例)時,改變顯示樣式 if (!PrimaryForm.Instance.isOnOrderedSongsPage || (!isCurrentlyPlaying && (!hasBeenPlayed || !isLatestInstance))) { // 當滑鼠移到歌曲上時,變更歌曲名稱為黃色 songLabel.ForeColor = Color.Yellow; // 變更歌手名稱為黃色 artistLabel.ForeColor = Color.Yellow; // 增強分隔線的亮度,使其更明顯 separatorPanel.BackColor = Color.FromArgb(120, 255, 255, 255); } }; // 定義滑鼠離開 (MouseLeave) 事件的處理程序 EventHandler mouseLeave = (sender, e) => { // 判斷是否處於「已點歌曲」頁面 if (PrimaryForm.Instance.isOnOrderedSongsPage) { // 如果當前歌曲正在播放,則維持綠色顯示 if (isCurrentlyPlaying) { songLabel.ForeColor = Color.LimeGreen; } // 如果該歌曲已播放完成,且是該歌曲的最新實例,則變為灰色 else if (hasBeenPlayed && isLatestInstance) { songLabel.ForeColor = Color.Gray; } // 其他情況,則維持白色 else { songLabel.ForeColor = Color.White; } } else { // 若不在「已點歌曲」頁面,則默認為白色 songLabel.ForeColor = Color.White; } // 恢復歌手名稱的顏色為預設的藍色 artistLabel.ForeColor = Color.FromArgb(30, 144, 255); // 恢復分隔線的顏色為半透明白色 separatorPanel.BackColor = Color.FromArgb(80, 255, 255, 255); }; // 添加事件处理 songLabel.Click += PrimaryForm.Instance.Label_Click; artistLabel.Click += PrimaryForm.Instance.Label_Click; // 滑動事件調整位置 songLabel.MouseDown += MultiPagePanel_MouseDown; songLabel.MouseMove += MultiPagePanel_MouseMove; songLabel.MouseUp += MultiPagePanel_MouseUp; songLabel.MouseEnter += mouseEnter; songLabel.MouseLeave += mouseLeave; artistLabel.MouseEnter += mouseEnter; artistLabel.MouseLeave += mouseLeave; // 滑動事件調整位置 artistLabel.MouseDown += MultiPagePanel_MouseDown; artistLabel.MouseMove += MultiPagePanel_MouseMove; artistLabel.MouseUp += MultiPagePanel_MouseUp; separatorPanel.MouseEnter += mouseEnter; separatorPanel.MouseLeave += mouseLeave; // 按正确顺序添加控件 this.Controls.Add(separatorPanel); this.Controls.Add(songLabel); this.Controls.Add(artistLabel); // 确保控件层次正确 songLabel.BringToFront(); artistLabel.BringToFront(); } } } }