From 77ac202847ad3d41742485c18f635537fe996b4c Mon Sep 17 00:00:00 2001 From: jasonchenwork Date: Tue, 18 Mar 2025 14:57:49 +0800 Subject: [PATCH 1/9] =?UTF-8?q?SongSearch=E8=A8=BB=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PrimaryForm.SongSearch.BopomofoSearch.cs | 9 ++++++--- .../PrimaryForm.SongSearch.EnglishSearch.cs | 14 ++++++++------ .../SongSearch/PrimaryForm.SongSearch.cs | 1 + 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.BopomofoSearch.cs b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.BopomofoSearch.cs index 7c6eaa8..dcae270 100644 --- a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.BopomofoSearch.cs +++ b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.BopomofoSearch.cs @@ -8,7 +8,7 @@ using System.Collections.Generic; using IniParser; using IniParser.Model; using System.Text; - +/* Song Search with ZhuYin */ namespace DualScreenDemo { public partial class PrimaryForm @@ -32,6 +32,8 @@ namespace DualScreenDemo var configData = LoadConfigData(); + /* 抓注音圖檔(ZhuYinSongs) 來自configData的資料 */ + /* 要確認路經需確認configData內容值 */ string imagePath = Path.Combine(Application.StartupPath, configData["ImagePaths"]["ZhuYinSongs"]); ShowImageOnPictureBoxZhuYinSongs(Path.Combine(Application.StartupPath, imagePath)); @@ -45,7 +47,7 @@ namespace DualScreenDemo SetZhuYinSongsAndButtonsVisibility(true); pictureBoxZhuYinSongs.Visible = true; } - + /* 初始化拼音按鈕 */ private void InitializePhoneticButtonsForSongs() { var data = LoadConfigData(); @@ -61,7 +63,7 @@ namespace DualScreenDemo CreatePhoneticButtonForSongs(i, buttonImages.normal, buttonImages.mouseDown, buttonImages.mouseOver); } } - + /* 按鈕設置顯示方式 可參考按鈕事件寫法 */ private void CreatePhoneticButtonForSongs(int index, string normalImagePath, string mouseDownImagePath, string mouseOverImagePath) { try @@ -210,6 +212,7 @@ namespace DualScreenDemo inputBoxZhuYinSongs.TextChanged += (sender, e) => { + /* 搜尋結果顯示到前歌單點選 */ string searchText = inputBoxZhuYinSongs.Text; var searchResults = allSongs.Where(song => song.PhoneticNotation.StartsWith(searchText)).ToList(); currentPage = 0; diff --git a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.EnglishSearch.cs b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.EnglishSearch.cs index ac459a9..19de466 100644 --- a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.EnglishSearch.cs +++ b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.EnglishSearch.cs @@ -7,11 +7,12 @@ using System.Drawing; using IniParser; using IniParser.Model; using System.Text; - +/* 歌曲查詢 英文輸入 */ namespace DualScreenDemo { public partial class PrimaryForm { + /* 主頁面設計 */ private PictureBox pictureBoxEnglishSongs; private Button[] numberButtonsForSongs; @@ -53,7 +54,7 @@ namespace DualScreenDemo var data = LoadConfigData(); numberButtonCoords = LoadButtonCoordinates(data, "NumberButtonCoordinates", 10); var buttonImages = LoadButtonImages(data, "NumberButtonImages", 10); - + /* 按鈕圖片路徑設置 */ numberButtonsForSongs = new Button[10]; for (int i = 0; i < 10; i++) { @@ -81,7 +82,7 @@ namespace DualScreenDemo this.Controls.Add(numberButtonsForSongs[i]); } } - + /* 按鈕按下事件 */ private void NumberButtonForSongs_Click(object sender, EventArgs e) { @@ -95,6 +96,7 @@ namespace DualScreenDemo } } + /* 鍵盤對應按鈕位置 */ private void InitializeLetterButtonsForEnglishSongs() { var data = LoadConfigData(); @@ -227,7 +229,7 @@ namespace DualScreenDemo } private void InitializeInputBoxEnglishSongs() - { + { /* 英文輸入介面設定,參考 config.ini */ try { var parser = new FileIniDataParser(); @@ -260,7 +262,7 @@ namespace DualScreenDemo }; ResizeAndPositionControl(inputBoxEnglishSongs, x, y, width, height); - + /*搜尋結果 傳回點歌介面*/ inputBoxEnglishSongs.TextChanged += (sender, e) => { string searchText = inputBoxEnglishSongs.Text; @@ -280,7 +282,7 @@ namespace DualScreenDemo Console.WriteLine($"An error occurred: {ex.Message}"); } } - + /* 圖片位置設置 */ private void ShowImageOnPictureBoxEnglishSongs(string imagePath) { try diff --git a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.cs b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.cs index 4ae7d07..37823f2 100644 --- a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.cs +++ b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.cs @@ -4,6 +4,7 @@ using System.Windows.Forms; namespace DualScreenDemo { + /* 建構子創立,程式進入初始位置,所有搜尋初始化設置 */ public partial class PrimaryForm { private Button zhuyinSearchSongButton; From 27b9dcc4de1dd5ca6c7f6cf19274e8a601226b37 Mon Sep 17 00:00:00 2001 From: jasonchenwork Date: Tue, 18 Mar 2025 15:21:33 +0800 Subject: [PATCH 2/9] =?UTF-8?q?gitignore=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9451532..b737457 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ Superstar.mdf Superstar_log.ldf .vs build.bat -DualScreenKTVPlayStation.exe \ No newline at end of file +DualScreenKTVPlayStation.exe +themes/superstar/_www/ \ No newline at end of file From fbd988de09e90286653abbc00bf2bb74e615f9ca Mon Sep 17 00:00:00 2001 From: jasonchenwork Date: Tue, 18 Mar 2025 16:59:13 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E5=AD=97=E6=95=B8=E9=8D=B5=E7=9B=A4?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=B7=AF=E5=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PrimaryForm.SongSearch.WordCountSearch.cs | 2 +- config.ini | 80 ++++++++++++++++++- 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.WordCountSearch.cs b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.WordCountSearch.cs index 2f7c6e9..7a4ed07 100644 --- a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.WordCountSearch.cs +++ b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.WordCountSearch.cs @@ -10,7 +10,7 @@ namespace DualScreenDemo { private void WordCountSearchSong_Click(object sender, EventArgs e) - { + { zhuyinSearchSongButton.BackgroundImage = zhuyinSearchSongNormalBackground; englishSearchSongButton.BackgroundImage = englishSearchSongNormalBackground; pinyinSearchSongButton.BackgroundImage = pinyinSearchSongNormalBackground; diff --git a/config.ini b/config.ini index 7951d4a..e68d421 100644 --- a/config.ini +++ b/config.ini @@ -7,6 +7,7 @@ ZhuYinSongs = themes\superstar\歌名\注音\VOD_歌名查詢_注音查詢(按 EnglishSongs = themes\superstar\歌名\英文\VOD_歌名查詢_英文查詢(按鍵)_歌星查詢-注音查詢_未按.png PinYinSongs = themes\superstar\歌星\拼音\VOD_歌星查詢_拼音查詢(按鍵)_歌星查詢-注音查詢_未按.png HandWritingSongs = themes\superstar\歌星\手寫\3.歌星查詢(手寫按鍵)_未按.png +WordCountSongs = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)_未按.png [PictureBoxZhuYinSingers] X = 130 @@ -44,6 +45,12 @@ Y = 350 Width = 1079 Height = 394 +[PictureBoxWordCountSongs] +X = 130 +Y = 350 +Width = 1079 +Height = 394 + [PhoneticSymbols] Symbols=ㄅ,ㄉ,ㄍ,ㄐ,ㄓ,ㄗ,ㄛ,ㄡ,ㄤ,ㄧ,ㄆ,ㄊ,ㄎ,ㄑ,ㄔ,ㄘ,ㄜ,ㄢ,ㄦ,ㄨ,ㄇ,ㄋ,ㄏ,ㄒ,ㄕ,ㄙ,ㄞ,ㄣ,ㄩ,ㄈ,ㄌ, ,ㄖ,ㄚ,ㄠ @@ -567,6 +574,67 @@ normal = themes\superstar\歌星\手寫\3.歌星查詢(手寫按鍵)_關閉.png mouseOver = themes\superstar\歌星\手寫\3.歌星查詢(手寫按鍵)_關閉.png mouseDown = themes\superstar\歌星\手寫\3.歌星查詢(手寫按鍵)_關閉 複本.png +[NumberButtonCoordinatesWithWordCount] +button1 = 157,201,27,32 +button2 = 187,201,27,32 +button3 = 217,201,27,32 +button4 = 247,201,27,32 +button5 = 277,200,27,32 +button6 = 307,201,27,32 +button7 = 337,201,27,32 +button8 = 367,201,27,32 +button9 = 397,201,27,32 +button10 = 427,201,27,32 + + +[NumberButtonImagesWithWordCount] +button0_normal = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-02.png +button0_mouseDown = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-17.png +button0_mouseOver = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-02.png +button1_normal = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-03.png +button1_mouseDown = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-18.png +button1_mouseOver = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-03.png +button2_normal = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-04.png +button2_mouseDown = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-19.png +button2_mouseOver = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-04.png +button3_normal = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-05.png +button3_mouseDown = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-20.png +button3_mouseOver = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-05.png +button4_normal = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-06.png +button4_mouseDown = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-21.png +button4_mouseOver = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-06.png +button5_normal = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-07.png +button5_mouseDown = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-22.png +button5_mouseOver = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-07.png +button6_normal = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-08.png +button6_mouseDown = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-23.png +button6_mouseOver = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-08.png +button7_normal = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-09.png +button7_mouseDown = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-24.png +button7_mouseOver = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-09.png +button8_normal = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-10.png +button8_mouseDown = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-25.png +button8_mouseOver = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-10.png +button9_normal = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-11.png +button9_mouseDown = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-26.png +button9_mouseOver = themes\superstar\歌名\編號\VOD_歌名查詢_編號查詢(按鍵)-11.png + +[ModifyButtonImagesWordCount] +normal = themes\superstar\歌星\拼音\VOD_歌名查詢_編號查詢(按鍵)-13.png +mouseOver = themes\superstar\歌星\拼音\VOD_歌名查詢_編號查詢(按鍵)-13.png +mouseDown = themes\superstar\歌星\拼音\VOD_歌名查詢_編號查詢(按鍵)-28.png + +[ClearButtonImagesWordCount] +normal = themes\superstar\歌名\拼音\VOD_歌名查詢_編號查詢(按鍵)-14.png +mouseOver = themes\superstar\歌名\拼音\VOD_歌名查詢_編號查詢(按鍵)-14.png +mouseDown = themes\superstar\歌名\拼音\VOD_歌名查詢_編號查詢(按鍵)-29.png + +[CloseButtonImagesWordCount] +normal = themes\superstar\歌名\拼音\VOD_歌名查詢_編號查詢(按鍵)-15.png +mouseOver = themes\superstar\歌名\拼音\VOD_歌名查詢_編號查詢(按鍵)-15.png +mouseDown = themes\superstar\歌名\拼音\VOD_歌名查詢_編號查詢(按鍵)-30.png + + [InputBoxZhuYinSongs] X=150 Y=264 @@ -595,4 +663,14 @@ Height = 63 FontName = Times New Roman FontSize = 26 FontStyle = Regular -ForeColor = Black \ No newline at end of file +ForeColor = Black + +[InputBoxWordCountSongs] +X=150 +Y=264 +Width=596 +Height=63 +FontName=微軟正黑體 +FontSize=26 +FontStyle=Bold +ForeColor=Black \ No newline at end of file From 1253c605dbd1155e8369e147cf07aa51b8d10fbf Mon Sep 17 00:00:00 2001 From: jasonchenwork Date: Tue, 18 Mar 2025 17:21:15 +0800 Subject: [PATCH 4/9] =?UTF-8?q?=E6=8B=BC=E9=9F=B3=E6=AD=8C=E6=9B=B2?= =?UTF-8?q?=E6=9F=A5=E8=A9=A2=E5=AE=8C=E6=95=B4=E8=A8=BB=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PrimaryForm.SongSearch.PinyinSearch.cs | 263 +++++++++++++----- 1 file changed, 187 insertions(+), 76 deletions(-) diff --git a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.PinyinSearch.cs b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.PinyinSearch.cs index 818b3af..a31d9ba 100644 --- a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.PinyinSearch.cs +++ b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.PinyinSearch.cs @@ -10,15 +10,20 @@ namespace DualScreenDemo { public partial class PrimaryForm { + // 拼音歌曲的 PictureBox private PictureBox pictureBoxPinYinSongs; + // 存放拼音按鈕的陣列 private Button[] letterButtonsForPinYinSongs; + // 特殊功能按鈕(修改、清除、關閉) private Button modifyButtonPinYinSongs; private Button clearButtonPinYinSongs; private Button closeButtonPinYinSongs; + // 用於顯示輸入文字的輸入框 private RichTextBox inputBoxPinYinSongs; - + // 拼音歌曲搜尋按鈕點擊事件 private void PinyinSearchSongsButton_Click(object sender, EventArgs e) { + // 更新搜尋模式按鈕的背景圖 zhuyinSearchSongButton.BackgroundImage = zhuyinSearchSongNormalBackground; englishSearchSongButton.BackgroundImage = englishSearchSongNormalBackground; pinyinSearchSongButton.BackgroundImage = pinyinSearchSongActiveBackground; @@ -26,52 +31,71 @@ namespace DualScreenDemo handWritingSearchSongButton.BackgroundImage = handWritingSearchSongNormalBackground; numberSearchSongButton.BackgroundImage = numberSearchSongNormalBackground; - + // 讀取 config.ini 並獲取拼音圖片的路徑 var configData = LoadConfigData(); string pinyinImagePath = Path.Combine(Application.StartupPath, configData["ImagePaths"]["PinYinSongs"]); - + // 顯示拼音歌曲圖片 ShowImageOnPictureBoxPinYinSongs(Path.Combine(Application.StartupPath, pinyinImagePath)); - + // 設定不同模式的 UI 顯示 SetZhuYinSingersAndButtonsVisibility(false); SetEnglishSingersAndButtonsVisibility(false); SetPinYinSingersAndButtonsVisibility(false); SetPinYinSongsAndButtonsVisibility(true); pictureBoxPinYinSongs.Visible = true; } - + // 初始化拼音按鈕 private void InitializeLetterButtonsForPinYinSongs() { + // 從設定檔 (config.ini) 讀取配置數據 var data = LoadConfigData(); + + // 從配置數據中載入拼音字母按鈕的影像 (包含正常、點擊、滑鼠懸停三種狀態) var buttonImages = LoadButtonImages(data, "PinYinLetterButtonImages", 26); + + // 定義 QWERTY 鍵盤排列的字母順序 string qwertyLayout = "QWERTYUIOPASDFGHJKLZXCVBNM"; + + // 初始化拼音按鈕陣列,長度為 26(對應英文字母) letterButtonsForPinYinSongs = new Button[26]; + // 迴圈遍歷 26 個字母,依序建立按鈕 for (int i = 0; i < 26; i++) { + // 從配置檔案讀取當前按鈕的座標資訊 (X, Y, Width, Height) var coords = data["PinYinLetterButtonCoordinates"][$"button{i}"].Split(','); + + // 建立拼音按鈕,並設定名稱、座標、影像與事件處理函式 letterButtonsForPinYinSongs[i] = CreateButton( - $"letterButton_{qwertyLayout[i]}", - (int.Parse(coords[0]), int.Parse(coords[1]), int.Parse(coords[2]), int.Parse(coords[3])), - buttonImages[$"button{i}"].normal, - buttonImages[$"button{i}"].mouseDown, - buttonImages[$"button{i}"].mouseOver, - LetterButtonPinYinSongs_Click + $"letterButton_{qwertyLayout[i]}", // 按鈕名稱,例如 "letterButton_Q" + (int.Parse(coords[0]), int.Parse(coords[1]), int.Parse(coords[2]), int.Parse(coords[3])), // 解析座標數據 + buttonImages[$"button{i}"].normal, // 正常狀態影像 + buttonImages[$"button{i}"].mouseDown, // 按下狀態影像 + buttonImages[$"button{i}"].mouseOver, // 滑鼠懸停狀態影像 + LetterButtonPinYinSongs_Click // 點擊事件處理函式 ); + + // 設定按鈕的標籤 (Tag) 為對應的字母,例如 Q、W、E... letterButtonsForPinYinSongs[i].Tag = qwertyLayout[i]; + + // 將按鈕新增到表單的控制項集合中,讓其顯示在介面上 this.Controls.Add(letterButtonsForPinYinSongs[i]); } } - + // 處理拼音按鈕點擊事件 private void LetterButtonPinYinSongs_Click(object sender, EventArgs e) { - + // 嘗試將觸發事件的物件轉換為 Button 類型 var button = sender as Button; + + // 檢查按鈕是否為 null,並確保該按鈕的 Tag 屬性不為 null if (button != null && button.Tag != null) { + // 確保輸入框 (inputBoxPinYinSongs) 是可見狀態 if (inputBoxPinYinSongs.Visible) { + // 將按鈕的標籤 (Tag) 轉換為字串,並附加到輸入框的文字內容中 inputBoxPinYinSongs.Text += button.Tag.ToString(); } } @@ -79,235 +103,321 @@ namespace DualScreenDemo private void InitializeButtonsForPinYinSongs() { + // 初始化拼音字母按鈕,根據 QWERTY 鍵盤佈局建立對應的按鈕 InitializeLetterButtonsForPinYinSongs(); + + // 初始化特殊功能按鈕,包括修改、清除和關閉按鈕 InitializeSpecialButtonsForPinYinSongs(); + + // 初始化拼音輸入框,讓使用者可以輸入拼音來搜尋歌曲 InitializeInputBoxPinYinSongs(); } private void InitializeSpecialButtonsForPinYinSongs() { + // 初始化「修改」按鈕,讓使用者可以刪除輸入框中的最後一個字母 InitializeModifyButtonPinYinSongs(); - + // 初始化「清除」按鈕,讓使用者可以清空輸入框的內容 InitializeClearButtonPinYinSongs(); - + // 初始化「關閉」按鈕,讓使用者可以關閉拼音輸入的 UI 元件 InitializeCloseButtonPinYinSongs(); } private void InitializeModifyButtonPinYinSongs() { + // 載入設定檔資料,取得特殊按鈕的相關配置 var data = LoadConfigData(); + + // 從設定檔讀取「修改按鈕」的座標位置與大小 modifyButtonPinYinCoords = LoadSpecialButtonCoordinates(data, "SpecialButtonCoordinates", "modifyButtonPinYinSongs"); + + // 從設定檔讀取「修改按鈕」的不同狀態圖片 (一般、滑鼠懸停、按下) var buttonImages = LoadButtonImages(data, "ModifyButtonImagesPinYin"); + // 創建「修改按鈕」,並綁定點擊事件 modifyButtonPinYinSongs = CreateSpecialButton( - "btnModifyPinYinSongs", - modifyButtonPinYinCoords, - buttonImages.normal, - buttonImages.mouseOver, - buttonImages.mouseDown, - ModifyButtonPinYinSongs_Click + "btnModifyPinYinSongs", // 按鈕名稱 + modifyButtonPinYinCoords, // 設定按鈕的座標與大小 + buttonImages.normal, // 設定按鈕的正常狀態圖片 + buttonImages.mouseOver, // 設定按鈕的滑鼠懸停圖片 + buttonImages.mouseDown, // 設定按鈕的按下狀態圖片 + ModifyButtonPinYinSongs_Click // 綁定按鈕的點擊事件處理函式 ); + } private void ModifyButtonPinYinSongs_Click(object sender, EventArgs e) { + // 檢查 `inputBoxPinYinSongs` 是否已被加入到 `Controls` 集合中 (確保輸入框存在) if (this.Controls.Contains(inputBoxPinYinSongs) && inputBoxPinYinSongs.Text.Length > 0) { + // 若 `inputBoxPinYinSongs` 有內容,刪除最後一個字母 inputBoxPinYinSongs.Text = inputBoxPinYinSongs.Text.Substring(0, inputBoxPinYinSongs.Text.Length - 1); } } private void InitializeClearButtonPinYinSongs() { + // 從設定檔載入資料 var data = LoadConfigData(); + + // 讀取清除按鈕的座標配置 (X, Y, Width, Height) clearButtonPinYinCoords = LoadSpecialButtonCoordinates(data, "SpecialButtonCoordinates", "clearButtonPinYinSongs"); + + // 載入清除按鈕的圖片 (一般狀態、滑鼠懸停、按下時的圖片) var buttonImages = LoadButtonImages(data, "ClearButtonImagesPinYin"); + // 建立「清除按鈕」並指定對應的座標與圖片 clearButtonPinYinSongs = CreateSpecialButton( - "btnClearPinYinSongs", - clearButtonPinYinCoords, - buttonImages.normal, - buttonImages.mouseOver, - buttonImages.mouseDown, - ClearButtonPinYinSongs_Click + "btnClearPinYinSongs", // 按鈕名稱 + clearButtonPinYinCoords, // 按鈕的座標與大小 + buttonImages.normal, // 按鈕的普通狀態圖片 + buttonImages.mouseOver, // 滑鼠懸停時的圖片 + buttonImages.mouseDown, // 滑鼠按下時的圖片 + ClearButtonPinYinSongs_Click // 點擊事件處理函式 ); + } private void ClearButtonPinYinSongs_Click(object sender, EventArgs e) { + // 檢查視窗內是否包含 inputBoxPinYinSongs 控制項,且輸入框內是否有文字 if (this.Controls.Contains(inputBoxPinYinSongs) && inputBoxPinYinSongs.Text.Length > 0) { + // 清空拼音輸入框的內容 inputBoxPinYinSongs.Text = ""; } } private void InitializeCloseButtonPinYinSongs() { + // 讀取設定檔中的按鈕配置數據 var data = LoadConfigData(); + + // 從設定檔中取得「關閉」按鈕的座標 closeButtonPinYinCoords = LoadSpecialButtonCoordinates(data, "SpecialButtonCoordinates", "closeButtonPinYinSongs"); + + // 從設定檔中讀取「關閉」按鈕的圖片 var buttonImages = LoadButtonImages(data, "CloseButtonImagesPinYin"); + // 建立「關閉」按鈕,並設定名稱、座標、按鈕圖片及點擊事件 closeButtonPinYinSongs = CreateSpecialButton( - "btnClosePinYinSongs", - closeButtonPinYinCoords, - buttonImages.normal, - buttonImages.mouseOver, - buttonImages.mouseDown, - CloseButtonPinYinSongs_Click + "btnClosePinYinSongs", // 按鈕名稱 + closeButtonPinYinCoords, // 按鈕座標 (X, Y, Width, Height) + buttonImages.normal, // 按鈕的普通狀態圖片 + buttonImages.mouseOver, // 滑鼠懸停時的圖片 + buttonImages.mouseDown, // 按下時的圖片 + CloseButtonPinYinSongs_Click // 點擊事件處理函式 ); + } private void CloseButtonPinYinSongs_Click(object sender, EventArgs e) { + // 隱藏拼音輸入的背景圖片 (可能是 UI 中的輸入框背景) pictureBoxPinYinSongs.Visible = false; + // 設定拼音輸入框與所有相關按鈕的可見性為 false SetPinYinSongsAndButtonsVisibility(false); + } private void InitializeInputBoxPinYinSongs() { try { + // 創建一個 INI 檔案解析器 var parser = new FileIniDataParser(); - parser.Parser.Configuration.AssigmentSpacer = ""; - parser.Parser.Configuration.CommentString = "#"; - parser.Parser.Configuration.CaseInsensitive = true; - - IniData data; + // 配置解析器的參數 + parser.Parser.Configuration.AssigmentSpacer = ""; // 設定 `=` 兩側沒有空格 + parser.Parser.Configuration.CommentString = "#"; // 使用 `#` 作為註解符號 + parser.Parser.Configuration.CaseInsensitive = true; // 參數名稱不區分大小寫 + + IniData data; // 儲存解析後的 INI 數據 + + // 讀取 `config.ini` 文件,使用 UTF-8 編碼 using (var reader = new StreamReader("config.ini", System.Text.Encoding.UTF8)) { data = parser.ReadData(reader); } - int x = int.Parse(data["InputBoxPinYinSongs"]["X"]); - int y = int.Parse(data["InputBoxPinYinSongs"]["Y"]); - int width = int.Parse(data["InputBoxPinYinSongs"]["Width"]); - int height = int.Parse(data["InputBoxPinYinSongs"]["Height"]); - string fontName = data["InputBoxPinYinSongs"]["FontName"]; - float fontSize = float.Parse(data["InputBoxPinYinSongs"]["FontSize"]); - FontStyle fontStyle = (FontStyle)Enum.Parse(typeof(FontStyle), data["InputBoxPinYinSongs"]["FontStyle"]); - Color foreColor = Color.FromName(data["InputBoxPinYinSongs"]["ForeColor"]); + // 從 INI 檔案讀取拼音輸入框的位置與大小 + int x = int.Parse(data["InputBoxPinYinSongs"]["X"]); // X 座標 + int y = int.Parse(data["InputBoxPinYinSongs"]["Y"]); // Y 座標 + int width = int.Parse(data["InputBoxPinYinSongs"]["Width"]); // 寬度 + int height = int.Parse(data["InputBoxPinYinSongs"]["Height"]); // 高度 + // 讀取字型設定 + string fontName = data["InputBoxPinYinSongs"]["FontName"]; // 字型名稱 + float fontSize = float.Parse(data["InputBoxPinYinSongs"]["FontSize"]); // 字體大小 + FontStyle fontStyle = (FontStyle)Enum.Parse(typeof(FontStyle), data["InputBoxPinYinSongs"]["FontStyle"]); // 字體樣式 + Color foreColor = Color.FromName(data["InputBoxPinYinSongs"]["ForeColor"]); // 文字顏色 + + // 創建拼音輸入框 (`RichTextBox`) inputBoxPinYinSongs = new RichTextBox { - Visible = false, - Name = "inputBoxPinYinSongs", - ForeColor = foreColor, - Font = new Font(fontName, fontSize / 900 * Screen.PrimaryScreen.Bounds.Height, fontStyle) + Visible = false, // 預設為隱藏 + Name = "inputBoxPinYinSongs", // 設定控制項名稱 + ForeColor = foreColor, // 設定文字顏色 + Font = new Font( + fontName, + fontSize / 900 * Screen.PrimaryScreen.Bounds.Height, // 根據螢幕大小調整字體 + fontStyle + ) }; + // 設定輸入框的位置與大小 ResizeAndPositionControl(inputBoxPinYinSongs, x, y, width, height); + // 綁定 `TextChanged` 事件 (當輸入內容改變時觸發搜尋) inputBoxPinYinSongs.TextChanged += (sender, e) => { string searchText = inputBoxPinYinSongs.Text; - var searchResults = allSongs.Where(song => song.PinyinNotation.StartsWith(searchText)).ToList(); - currentPage = 0; - currentSongList = searchResults; - totalPages = (int)Math.Ceiling((double)searchResults.Count / itemsPerPage); + // 根據拼音前綴篩選歌曲 + var searchResults = allSongs.Where(song => song.PinyinNotation.StartsWith(searchText)).ToList(); + + currentPage = 0; // 重置當前頁面索引 + currentSongList = searchResults; // 更新搜尋結果 + totalPages = (int)Math.Ceiling((double)searchResults.Count / itemsPerPage); // 計算總頁數 + + // 更新 UI,顯示搜尋結果 multiPagePanel.currentPageIndex = 0; multiPagePanel.LoadSongs(currentSongList); }; + // 將拼音輸入框加入視窗中 this.Controls.Add(inputBoxPinYinSongs); } catch (Exception ex) { + // 發生錯誤時輸出錯誤訊息 (避免程式崩潰) Console.WriteLine($"An error occurred: {ex.Message}"); } - } + } + // 讀取 PictureBoxPinYinSongs 的座標設定 private (int X, int Y, int Width, int Height) pictureBoxPinYinSongCoords; private void LoadPictureBoxPinYinSongCoordsFromConfig() { + // 創建一個 INI 檔案解析器 var parser = new FileIniDataParser(); + + // 讀取 `config.ini` 文件並解析成 `IniData` 對象 IniData data = parser.ReadFile("config.ini"); + // 取得 `PictureBoxPinYinSongs` 區段的設定值 var coords = data["PictureBoxPinYinSongs"]; + + // 解析 `X`, `Y`, `Width`, `Height`,並存入 `pictureBoxPinYinSongCoords` pictureBoxPinYinSongCoords = ( - int.Parse(coords["X"]), - int.Parse(coords["Y"]), - int.Parse(coords["Width"]), - int.Parse(coords["Height"]) + int.Parse(coords["X"]), // 解析 X 座標 + int.Parse(coords["Y"]), // 解析 Y 座標 + int.Parse(coords["Width"]), // 解析 寬度 + int.Parse(coords["Height"]) // 解析 高度 ); } - + // 顯示拼音歌曲圖片 private void ShowImageOnPictureBoxPinYinSongs(string imagePath) { - - LoadPictureBoxPinYinSongCoordsFromConfig(); + // 從設定檔載入 PictureBox 的座標與大小 + LoadPictureBoxPinYinSongCoordsFromConfig(); - - Bitmap originalImage = new Bitmap(imagePath); + // 使用指定的圖片路徑建立 Bitmap 影像 + Bitmap originalImage = new Bitmap(imagePath); - - Rectangle displayArea = new Rectangle(pictureBoxPinYinSongCoords.X, pictureBoxPinYinSongCoords.Y, pictureBoxPinYinSongCoords.Width, pictureBoxPinYinSongCoords.Height); + // 建立一個矩形,表示 PictureBox 應該顯示的範圍 + Rectangle displayArea = new Rectangle( + pictureBoxPinYinSongCoords.X, // 設定 X 座標 + pictureBoxPinYinSongCoords.Y, // 設定 Y 座標 + pictureBoxPinYinSongCoords.Width, // 設定 寬度 + pictureBoxPinYinSongCoords.Height // 設定 高度 + ); - - pictureBoxPinYinSongs.Image = originalImage; + // 將載入的圖片設定為 `pictureBoxPinYinSongs` 的影像 + pictureBoxPinYinSongs.Image = originalImage; + + // 調整 `PictureBox` 的大小與位置,使其符合 `displayArea` 的設定 + ResizeAndPositionPictureBox( + pictureBoxPinYinSongs, + displayArea.X, + displayArea.Y, + displayArea.Width, + displayArea.Height + ); + + // 顯示 `PictureBox` + pictureBoxPinYinSongs.Visible = true; - - ResizeAndPositionPictureBox(pictureBoxPinYinSongs, displayArea.X, displayArea.Y, displayArea.Width, displayArea.Height); - - pictureBoxPinYinSongs.Visible = true; } - + // 設定拼音模式的 UI 是否可見 private void SetPinYinSongsAndButtonsVisibility(bool isVisible) { + // 定義一個委派 (Action),用於更新 UI 控件的可見性 System.Action action = () => { + // 暫停佈局更新,以防止 UI 閃爍或重繪時出現異常 SuspendLayout(); + // 設定 `pictureBoxPinYinSongs` 的可見性 pictureBoxPinYinSongs.Visible = isVisible; - if (isVisible) pictureBoxPinYinSongs.BringToFront(); + if (isVisible) pictureBoxPinYinSongs.BringToFront(); // 確保顯示時位於最前方 + // 設定所有拼音字母按鈕的可見性 foreach (var button in letterButtonsForPinYinSongs) { button.Visible = isVisible; if (isVisible) button.BringToFront(); } + // 設定 `modifyButtonPinYinSongs` (修改按鈕) 的可見性 if (modifyButtonPinYinSongs != null) { modifyButtonPinYinSongs.Visible = isVisible; if (isVisible) modifyButtonPinYinSongs.BringToFront(); } + // 設定 `clearButtonPinYinSongs` (清除按鈕) 的可見性 if (clearButtonPinYinSongs != null) { clearButtonPinYinSongs.Visible = isVisible; if (isVisible) clearButtonPinYinSongs.BringToFront(); } + // 設定 `closeButtonPinYinSongs` (關閉按鈕) 的可見性 closeButtonPinYinSongs.Visible = isVisible; if (isVisible) closeButtonPinYinSongs.BringToFront(); + // 設定 `inputBoxPinYinSongs` (輸入框) 的可見性 inputBoxPinYinSongs.Visible = isVisible; if (isVisible) inputBoxPinYinSongs.BringToFront(); + // 恢復佈局,允許 UI 更新 ResumeLayout(); PerformLayout(); - + // 刷新 `pictureBoxPinYinSongs`,確保畫面更新 pictureBoxPinYinSongs.Refresh(); + + // 刷新拼音字母按鈕 foreach (var button in letterButtonsForPinYinSongs) { button.Refresh(); } - + // 刷新其他按鈕與輸入框 modifyButtonPinYinSongs.Refresh(); clearButtonPinYinSongs.Refresh(); closeButtonPinYinSongs.Refresh(); inputBoxPinYinSongs.Refresh(); }; + // 如果當前執行緒不是 UI 執行緒,則使用 Invoke 確保執行於 UI 執行緒 if (this.InvokeRequired) { this.Invoke(action); @@ -316,6 +426,7 @@ namespace DualScreenDemo { action(); } + } } } \ No newline at end of file From 873a8fee13ef14a92caf65a5b2380a34822e47d8 Mon Sep 17 00:00:00 2001 From: jasonchenwork Date: Tue, 18 Mar 2025 17:25:47 +0800 Subject: [PATCH 5/9] =?UTF-8?q?WordCount=E8=AA=BF=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.ini | 84 +++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/config.ini b/config.ini index e68d421..bd3421c 100644 --- a/config.ini +++ b/config.ini @@ -574,6 +574,47 @@ normal = themes\superstar\歌星\手寫\3.歌星查詢(手寫按鍵)_關閉.png mouseOver = themes\superstar\歌星\手寫\3.歌星查詢(手寫按鍵)_關閉.png mouseDown = themes\superstar\歌星\手寫\3.歌星查詢(手寫按鍵)_關閉 複本.png +[InputBoxZhuYinSongs] +X=150 +Y=264 +Width=596 +Height=63 +FontName=微軟正黑體 +FontSize=26 +FontStyle=Bold +ForeColor=Black + +[InputBoxEnglishSongs] +X = 408 +Y = 361 +Width = 444 +Height = 47 +FontName = Times New Roman +FontSize = 26 +FontStyle = Regular +ForeColor = Black + +[InputBoxPinYinSongs] +X = 154 +Y = 370 +Width = 593 +Height = 63 +FontName = Times New Roman +FontSize = 26 +FontStyle = Regular +ForeColor = Black + +[InputBoxWordCountSongs] +X=150 +Y=264 +Width=596 +Height=63 +FontName=微軟正黑體 +FontSize=26 +FontStyle=Bold +ForeColor=Black + + [NumberButtonCoordinatesWithWordCount] button1 = 157,201,27,32 button2 = 187,201,27,32 @@ -632,45 +673,4 @@ mouseDown = themes\superstar\歌名\拼音\VOD_歌名查詢_編號查詢(按鍵) [CloseButtonImagesWordCount] normal = themes\superstar\歌名\拼音\VOD_歌名查詢_編號查詢(按鍵)-15.png mouseOver = themes\superstar\歌名\拼音\VOD_歌名查詢_編號查詢(按鍵)-15.png -mouseDown = themes\superstar\歌名\拼音\VOD_歌名查詢_編號查詢(按鍵)-30.png - - -[InputBoxZhuYinSongs] -X=150 -Y=264 -Width=596 -Height=63 -FontName=微軟正黑體 -FontSize=26 -FontStyle=Bold -ForeColor=Black - -[InputBoxEnglishSongs] -X = 408 -Y = 361 -Width = 444 -Height = 47 -FontName = Times New Roman -FontSize = 26 -FontStyle = Regular -ForeColor = Black - -[InputBoxPinYinSongs] -X = 154 -Y = 370 -Width = 593 -Height = 63 -FontName = Times New Roman -FontSize = 26 -FontStyle = Regular -ForeColor = Black - -[InputBoxWordCountSongs] -X=150 -Y=264 -Width=596 -Height=63 -FontName=微軟正黑體 -FontSize=26 -FontStyle=Bold -ForeColor=Black \ No newline at end of file +mouseDown = themes\superstar\歌名\拼音\VOD_歌名查詢_編號查詢(按鍵)-30.png \ No newline at end of file From 3b3111d2271532e2651ded643fa935db1f567ef1 Mon Sep 17 00:00:00 2001 From: jasonchenwork Date: Wed, 19 Mar 2025 09:35:34 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E6=AD=8C=E6=9B=B2=E6=9F=A5=E8=A9=A2?= =?UTF-8?q?=E5=AD=97=E6=95=B8=E8=A8=BB=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PrimaryForm.SongSearch.WordCountSearch.cs | 347 ++++++++++-------- 1 file changed, 201 insertions(+), 146 deletions(-) diff --git a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.WordCountSearch.cs b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.WordCountSearch.cs index 7a4ed07..e8d7b13 100644 --- a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.WordCountSearch.cs +++ b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.WordCountSearch.cs @@ -8,182 +8,237 @@ namespace DualScreenDemo { public partial class PrimaryForm { - + /// + /// 當使用者點擊「詞數查歌」按鈕時,切換到詞數查歌模式,更新 UI 並顯示對應的查歌界面。 + /// + /// 觸發事件的按鈕。 + /// 事件參數。 private void WordCountSearchSong_Click(object sender, EventArgs e) { - zhuyinSearchSongButton.BackgroundImage = zhuyinSearchSongNormalBackground; - englishSearchSongButton.BackgroundImage = englishSearchSongNormalBackground; - pinyinSearchSongButton.BackgroundImage = pinyinSearchSongNormalBackground; - wordCountSearchSongButton.BackgroundImage = wordCountSearchSongActiveBackground; - handWritingSearchSongButton.BackgroundImage = handWritingSearchNormalBackground; - numberSearchSongButton.BackgroundImage = numberSearchSongNormalBackground; + // 設定查歌模式按鈕的背景圖片 + zhuyinSearchSongButton.BackgroundImage = zhuyinSearchSongNormalBackground; // 注音查歌(普通狀態) + englishSearchSongButton.BackgroundImage = englishSearchSongNormalBackground; // 英文查歌(普通狀態) + pinyinSearchSongButton.BackgroundImage = pinyinSearchSongNormalBackground; // 拼音查歌(普通狀態) + wordCountSearchSongButton.BackgroundImage = wordCountSearchSongActiveBackground; // 詞數查歌(選中狀態) + handWritingSearchSongButton.BackgroundImage = handWritingSearchNormalBackground; // 手寫查歌(普通狀態) + numberSearchSongButton.BackgroundImage = numberSearchSongNormalBackground; // 數字查歌(普通狀態) + // 顯示詞數查歌對應的圖片 ShowImageOnPictureBoxWordCount(Path.Combine(Application.StartupPath, @"themes\superstar\6-1.png")); + // 設定詞數查歌的 PictureBox 和按鈕的可見性 SetPictureBoxWordCountAndButtonsVisibility(true); - pictureBoxWordCount.Visible = true; - } + pictureBoxWordCount.Visible = true; // 顯示 PictureBoxWordCount + } + /// + /// 顯示詞數查歌對應的圖片 + /// + /// 圖片路徑 private void ShowImageOnPictureBoxWordCount(string imagePath) { + // 載入原始圖片 Bitmap originalImage = new Bitmap(imagePath); - + // 定義裁切區域 (起始座標: 593, 135,寬度: 507,高度: 508) Rectangle cropArea = new Rectangle(593, 135, 507, 508); - + // 裁切圖片,獲得指定範圍的影像 Bitmap croppedImage = CropImage(originalImage, cropArea); - + // 將裁切後的圖片顯示在 pictureBoxWordCount 上 pictureBoxWordCount.Image = croppedImage; - - - ResizeAndPositionPictureBox(pictureBoxWordCount, cropArea.X + offsetXWordCount, cropArea.Y + offsetXWordCount, cropArea.Width, cropArea.Height); - + + // 調整 pictureBoxWordCount 的大小與位置 + ResizeAndPositionPictureBox(pictureBoxWordCount, + cropArea.X + offsetXWordCount, // X 座標 (包含位移量) + cropArea.Y + offsetYWordCount, // Y 座標 (包含位移量) + cropArea.Width, // 寬度 + cropArea.Height // 高度 + ); + + // 顯示 pictureBoxWordCount pictureBoxWordCount.Visible = true; + } - private void InitializeButtonsForPictureBoxWordCount() - { - - int[,] coords = new int[,] + /// + /// 初始化「詞數查歌」模式的按鈕與輸入框,並根據螢幕解析度進行調整。 + /// + private void InitializeButtonsForPictureBoxWordCount() { - {651, 292, 752, 400}, - {760, 292, 861, 400}, - {869, 292, 972, 399}, - {652, 401, 752, 502}, - {760, 401, 861, 504}, - {869, 398, 972, 502}, - {651, 502, 753, 607}, - {759, 504, 863, 607}, - {869, 503, 973, 608}, - {981, 501, 1083, 609} - }; - - int screenW = Screen.PrimaryScreen.Bounds.Width; - int screenH = Screen.PrimaryScreen.Bounds.Height; - - - float widthRatio = screenW / (float)1440; - float heightRatio = screenH / (float)900; - - numberButtonsWordCount = new Button[10]; - - for (int i = 0; i < numberButtonsWordCount.Length; i++) - { - numberButtonsWordCount[i] = new Button(); - - - ConfigureButton( - numberButtonsWordCount[i], - coords[i, 0], - coords[i, 1], - coords[i, 2] - coords[i, 0], - coords[i, 3] - coords[i, 1], - - resizedNormalStateImageFor6_1, - resizedMouseOverImageFor6_1, - resizedMouseDownImageFor6_1, - null - ); - - int newXForWordCount = (int)(((numberButtonsWordCount[i].Location.X / widthRatio) + offsetXWordCount) * widthRatio); - int newYForWordCount = (int)(((numberButtonsWordCount[i].Location.Y / heightRatio) + offsetYWordCount) * heightRatio); - numberButtonsWordCount[i].Location = new Point(newXForWordCount, newYForWordCount); - - - numberButtonsWordCount[i].Name = "NumberButtonWordCount" + i; - - numberButtonsWordCount[i].Tag = (i + 1).ToString(); - if (i == 9) + // 定義數字按鈕的座標範圍 (左上角 X, Y 以及右下角 X, Y) + int[,] coords = new int[,] { - numberButtonsWordCount[i].Name = "NumberButtonWordCount0"; - numberButtonsWordCount[i].Tag = "0"; + {651, 292, 752, 400}, // 1 + {760, 292, 861, 400}, // 2 + {869, 292, 972, 399}, // 3 + {652, 401, 752, 502}, // 4 + {760, 401, 861, 504}, // 5 + {869, 398, 972, 502}, // 6 + {651, 502, 753, 607}, // 7 + {759, 504, 863, 607}, // 8 + {869, 503, 973, 608}, // 9 + {981, 501, 1083, 609} // 0 + }; + + // 取得螢幕解析度 + int screenW = Screen.PrimaryScreen.Bounds.Width; + int screenH = Screen.PrimaryScreen.Bounds.Height; + + // 計算寬高比例,供座標縮放使用 + float widthRatio = screenW / (float)1440; + float heightRatio = screenH / (float)900; + + // 建立數字按鈕陣列 + numberButtonsWordCount = new Button[10]; + + // 依序建立 0-9 按鈕 + for (int i = 0; i < numberButtonsWordCount.Length; i++) + { + numberButtonsWordCount[i] = new Button(); + + // 設定按鈕屬性 (位置、大小、圖片) + ConfigureButton( + numberButtonsWordCount[i], + coords[i, 0], + coords[i, 1], + coords[i, 2] - coords[i, 0], // 計算按鈕寬度 + coords[i, 3] - coords[i, 1], // 計算按鈕高度 + resizedNormalStateImageFor6_1, + resizedMouseOverImageFor6_1, + resizedMouseDownImageFor6_1, + null + ); + + // 調整按鈕位置,使其適應不同解析度 + int newXForWordCount = (int)(((numberButtonsWordCount[i].Location.X / widthRatio) + offsetXWordCount) * widthRatio); + int newYForWordCount = (int)(((numberButtonsWordCount[i].Location.Y / heightRatio) + offsetYWordCount) * heightRatio); + numberButtonsWordCount[i].Location = new Point(newXForWordCount, newYForWordCount); + + // 設定按鈕名稱 + numberButtonsWordCount[i].Name = "NumberButtonWordCount" + i; + numberButtonsWordCount[i].Tag = (i + 1).ToString(); + + // 處理按鈕 0 的特殊名稱與標籤 + if (i == 9) + { + numberButtonsWordCount[i].Name = "NumberButtonWordCount0"; + numberButtonsWordCount[i].Tag = "0"; + } + + // 設定點擊事件 + numberButtonsWordCount[i].Click += WordCountButton_Click; + + // 將按鈕加入視窗控制項 + this.Controls.Add(numberButtonsWordCount[i]); } - - numberButtonsWordCount[i].Click += WordCountButton_Click; + // 建立「修改」按鈕 (Modify) + modifyButtonWordCount = new Button { + Name = "ModifyButtonWordCount", + Tag = "Modify", + Visible = false + }; + ConfigureButton(modifyButtonWordCount, 978, 292, 1081 - 978, 397 - 292, + resizedNormalStateImageFor6_1, resizedMouseOverImageFor6_1, resizedMouseDownImageFor6_1, + ModifyButtonWordCount_Click); - - this.Controls.Add(numberButtonsWordCount[i]); + // 調整「修改」按鈕的位置 + int newX = (int)(((modifyButtonWordCount.Location.X / widthRatio) + offsetXWordCount) * widthRatio); + int newY = (int)(((modifyButtonWordCount.Location.Y / heightRatio) + offsetYWordCount) * heightRatio); + modifyButtonWordCount.Location = new Point(newX, newY); + + // 加入「修改」按鈕至視窗 + this.Controls.Add(modifyButtonWordCount); + + // 建立「關閉」按鈕 (Close) + closeButtonWordCount = new Button { + Name = "CloseButtonWordCount", + Tag = "Close", + Visible = false + }; + ConfigureButton(closeButtonWordCount, 982, 147, 1082 - 982, 250 - 147, + resizedNormalStateImageFor6_1, resizedMouseOverImageFor6_1, resizedMouseDownImageFor6_1, + CloseButtonWordCount_Click); + + // 調整「關閉」按鈕的位置 + newX = (int)(((closeButtonWordCount.Location.X / widthRatio) + offsetXWordCount) * widthRatio); + newY = (int)(((closeButtonWordCount.Location.Y / heightRatio) + offsetYWordCount) * heightRatio); + closeButtonWordCount.Location = new Point(newX, newY); + + // 加入「關閉」按鈕至視窗 + this.Controls.Add(closeButtonWordCount); + + // 建立輸入框 (RichTextBox) 供使用者輸入詞數 + inputBoxWordCount = new RichTextBox(); + inputBoxWordCount.Name = "inputBoxWordCount"; + + // 設定輸入框位置與大小 + ResizeAndPositionControl(inputBoxWordCount, 645 + offsetXWordCount, 197 + offsetYWordCount, 986 - 645, 281 - 197); + inputBoxWordCount.ForeColor = Color.Black; + inputBoxWordCount.Font = new Font("細明體", (float)26 / 900 * Screen.PrimaryScreen.Bounds.Height, FontStyle.Regular); + + // 設定輸入框內容變更時的處理邏輯 + inputBoxWordCount.TextChanged += (sender, e) => + { + string searchText = inputBoxWordCount.Text; + int targetLength = 0; + + // 檢查輸入的是否為數字 + if (int.TryParse(searchText, out targetLength)) + { + // 根據詞數長度篩選歌曲 + var searchResults = allSongs.Where(song => song.Song.Replace(" ", "").Length == targetLength).ToList(); + currentPage = 0; + currentSongList = searchResults; + totalPages = (int)Math.Ceiling((double)searchResults.Count / itemsPerPage); + + // 更新多頁面面板 + multiPagePanel.currentPageIndex = 0; + multiPagePanel.LoadSongs(currentSongList); + } + else + { + // 若輸入非數字,則清空當前歌曲列表 + currentSongList.Clear(); + } + }; + + // 加入輸入框至視窗 + this.Controls.Add(inputBoxWordCount); } - - modifyButtonWordCount = new Button { - Name = "ModifyButtonWordCount", - Tag = "Modify", - Visible = false - }; - - ConfigureButton(modifyButtonWordCount, 978, 292, 1081 - 978, 397 - 292, resizedNormalStateImageFor6_1, resizedMouseOverImageFor6_1, resizedMouseDownImageFor6_1, ModifyButtonWordCount_Click); - int newX = (int)(((modifyButtonWordCount.Location.X / widthRatio) + offsetXWordCount) * widthRatio); - int newY = (int)(((modifyButtonWordCount.Location.Y / widthRatio) + offsetYWordCount) * heightRatio); - modifyButtonWordCount.Location = new Point(newX, newY); - this.Controls.Add(modifyButtonWordCount); - - - closeButtonWordCount = new Button { - Name = "CloseButtonWordCount", - Tag = "Close", - Visible = false - }; - - ConfigureButton(closeButtonWordCount, 982, 147, 1082 - 982, 250 - 147, resizedNormalStateImageFor6_1, resizedMouseOverImageFor6_1, resizedMouseDownImageFor6_1, CloseButtonWordCount_Click); - newX = (int)(((closeButtonWordCount.Location.X / widthRatio) + offsetXWordCount) * widthRatio); - newY = (int)(((closeButtonWordCount.Location.Y / widthRatio) + offsetYWordCount) * heightRatio); - closeButtonWordCount.Location = new Point(newX, newY); - this.Controls.Add(closeButtonWordCount); - - inputBoxWordCount = new RichTextBox(); - inputBoxWordCount.Name = "inputBoxWordCount"; - ResizeAndPositionControl(inputBoxWordCount, 645 + offsetXWordCount, 197 + offsetYWordCount, 986 - 645, 281 - 197); - inputBoxWordCount.ForeColor = Color.Black; - inputBoxWordCount.Font = new Font("細明體", (float)26 / 900 * Screen.PrimaryScreen.Bounds.Height, FontStyle.Regular); - - inputBoxWordCount.TextChanged += (sender, e) => - { - string searchText = inputBoxWordCount.Text; - int targetLength = 0; - - - if (int.TryParse(searchText, out targetLength)) - { - - var searchResults = allSongs.Where(song => song.Song.Replace(" ", "").Length == targetLength).ToList(); - currentPage = 0; - currentSongList = searchResults; - totalPages = (int)Math.Ceiling((double)searchResults.Count / itemsPerPage); - - multiPagePanel.currentPageIndex = 0; - multiPagePanel.LoadSongs(currentSongList); - } - else - { - - currentSongList.Clear(); - } - }; - - this.Controls.Add(inputBoxWordCount); - } - private void WordCountButton_Click(object sender, EventArgs e) - { - - - var button = sender as Button; - if (button != null && button.Tag != null) + /// + /// 處理數字按鈕的點擊事件,將按鈕對應的數字 (Tag) 加入輸入框 inputBoxWordCount 中。 + /// + /// 觸發事件的按鈕 + /// 事件參數 + private void WordCountButton_Click(object sender, EventArgs e) { - inputBoxWordCount.Text += button.Tag.ToString(); - } - } + // 嘗試將 sender 轉換為 Button 類型 + var button = sender as Button; - private void CloseButtonWordCount_Click(object sender, EventArgs e) - { - - SetPictureBoxWordCountAndButtonsVisibility(false); - } + // 確保按鈕不為空,且擁有有效的 Tag 值 + if (button != null && button.Tag != null) + { + // 將按鈕的 Tag 值 (數字) 追加到輸入框中 + inputBoxWordCount.Text += button.Tag.ToString(); + } + } + + /// + /// 關閉詞數輸入界面,隱藏相關的 PictureBox 和按鈕。 + /// + /// 觸發事件的按鈕。 + /// 事件參數。 + private void CloseButtonWordCount_Click(object sender, EventArgs e) + { + // 設定詞數輸入界面及其按鈕的可見性為 false,使其隱藏 + SetPictureBoxWordCountAndButtonsVisibility(false); + } } } \ No newline at end of file From 53290dda0e7303b6f0ec035aff6a1eb9d8e22000 Mon Sep 17 00:00:00 2001 From: jasonchenwork Date: Wed, 19 Mar 2025 10:05:08 +0800 Subject: [PATCH 7/9] =?UTF-8?q?=E6=AD=8C=E6=9B=B2=E6=9F=A5=E8=A9=A2?= =?UTF-8?q?=E6=8B=BC=E9=9F=B3=E8=A8=BB=E8=A7=A3=E5=84=AA=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PrimaryForm.SongSearch.PinyinSearch.cs | 138 ++++++++++++------ 1 file changed, 95 insertions(+), 43 deletions(-) diff --git a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.PinyinSearch.cs b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.PinyinSearch.cs index a31d9ba..5a0d7f5 100644 --- a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.PinyinSearch.cs +++ b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.PinyinSearch.cs @@ -45,7 +45,9 @@ namespace DualScreenDemo SetPinYinSongsAndButtonsVisibility(true); pictureBoxPinYinSongs.Visible = true; } - // 初始化拼音按鈕 + /// + /// 初始化拼音按鈕 + /// private void InitializeLetterButtonsForPinYinSongs() { // 從設定檔 (config.ini) 讀取配置數據 @@ -83,7 +85,11 @@ namespace DualScreenDemo this.Controls.Add(letterButtonsForPinYinSongs[i]); } } - // 處理拼音按鈕點擊事件 + /// + /// 處理拼音按鈕點擊事件 + /// + /// 觸發事件按鈕 + /// 事件參數 private void LetterButtonPinYinSongs_Click(object sender, EventArgs e) { // 嘗試將觸發事件的物件轉換為 Button 類型 @@ -101,43 +107,55 @@ namespace DualScreenDemo } } + /// + /// 初始化拼音輸入相關的 UI 控件,包括字母按鈕、特殊功能按鈕(修改、清除、關閉),以及拼音輸入框。 + /// private void InitializeButtonsForPinYinSongs() { // 初始化拼音字母按鈕,根據 QWERTY 鍵盤佈局建立對應的按鈕 InitializeLetterButtonsForPinYinSongs(); - // 初始化特殊功能按鈕,包括修改、清除和關閉按鈕 + // 初始化特殊功能按鈕(修改、清除、關閉) InitializeSpecialButtonsForPinYinSongs(); - // 初始化拼音輸入框,讓使用者可以輸入拼音來搜尋歌曲 + // 初始化拼音輸入框,使用者可透過輸入拼音來搜尋歌曲 InitializeInputBoxPinYinSongs(); } + /// + /// 初始化拼音輸入的特殊功能按鈕,包括: + /// 1. 修改按鈕 - 刪除輸入框中的最後一個字母 + /// 2. 清除按鈕 - 清空輸入框的內容 + /// 3. 關閉按鈕 - 隱藏拼音輸入的 UI 元件 + /// private void InitializeSpecialButtonsForPinYinSongs() { - - // 初始化「修改」按鈕,讓使用者可以刪除輸入框中的最後一個字母 + // 初始化「修改」按鈕(刪除輸入框最後一個字母) InitializeModifyButtonPinYinSongs(); - // 初始化「清除」按鈕,讓使用者可以清空輸入框的內容 + // 初始化「清除」按鈕(清空輸入框內容) InitializeClearButtonPinYinSongs(); - // 初始化「關閉」按鈕,讓使用者可以關閉拼音輸入的 UI 元件 + // 初始化「關閉」按鈕(關閉拼音輸入 UI) InitializeCloseButtonPinYinSongs(); } + + /// + /// 初始化「修改」按鈕,提供刪除拼音輸入框最後一個字母的功能。 + /// private void InitializeModifyButtonPinYinSongs() { - // 載入設定檔資料,取得特殊按鈕的相關配置 + // 讀取設定檔,載入特殊按鈕的配置資料 var data = LoadConfigData(); - // 從設定檔讀取「修改按鈕」的座標位置與大小 + // 從設定檔取得「修改按鈕」的座標與大小 modifyButtonPinYinCoords = LoadSpecialButtonCoordinates(data, "SpecialButtonCoordinates", "modifyButtonPinYinSongs"); - // 從設定檔讀取「修改按鈕」的不同狀態圖片 (一般、滑鼠懸停、按下) + // 讀取「修改按鈕」的圖片資源(一般狀態、滑鼠懸停、按下) var buttonImages = LoadButtonImages(data, "ModifyButtonImagesPinYin"); - // 創建「修改按鈕」,並綁定點擊事件 + // 創建「修改」按鈕,並綁定點擊事件 modifyButtonPinYinSongs = CreateSpecialButton( "btnModifyPinYinSongs", // 按鈕名稱 modifyButtonPinYinCoords, // 設定按鈕的座標與大小 @@ -146,43 +164,51 @@ namespace DualScreenDemo buttonImages.mouseDown, // 設定按鈕的按下狀態圖片 ModifyButtonPinYinSongs_Click // 綁定按鈕的點擊事件處理函式 ); - } + /// + /// 「修改」按鈕點擊事件:刪除拼音輸入框 (`inputBoxPinYinSongs`) 中的最後一個字母。 + /// private void ModifyButtonPinYinSongs_Click(object sender, EventArgs e) { - - // 檢查 `inputBoxPinYinSongs` 是否已被加入到 `Controls` 集合中 (確保輸入框存在) + // 確保 `inputBoxPinYinSongs` 存在於視窗控制項集合內,且輸入框內有文字 if (this.Controls.Contains(inputBoxPinYinSongs) && inputBoxPinYinSongs.Text.Length > 0) { - // 若 `inputBoxPinYinSongs` 有內容,刪除最後一個字母 + // 刪除輸入框內的最後一個字母 inputBoxPinYinSongs.Text = inputBoxPinYinSongs.Text.Substring(0, inputBoxPinYinSongs.Text.Length - 1); } } + + /// + /// 初始化「清除」按鈕 (`clearButtonPinYinSongs`),用於清空拼音輸入框 (`inputBoxPinYinSongs`)。 + /// private void InitializeClearButtonPinYinSongs() { // 從設定檔載入資料 var data = LoadConfigData(); - // 讀取清除按鈕的座標配置 (X, Y, Width, Height) + // 讀取「清除」按鈕的座標配置 (X, Y, Width, Height) clearButtonPinYinCoords = LoadSpecialButtonCoordinates(data, "SpecialButtonCoordinates", "clearButtonPinYinSongs"); - // 載入清除按鈕的圖片 (一般狀態、滑鼠懸停、按下時的圖片) + // 載入「清除」按鈕的圖片 (一般狀態、滑鼠懸停、按下時的圖片) var buttonImages = LoadButtonImages(data, "ClearButtonImagesPinYin"); - // 建立「清除按鈕」並指定對應的座標與圖片 + // 建立「清除」按鈕,設定對應的座標與圖片,並綁定點擊事件 clearButtonPinYinSongs = CreateSpecialButton( "btnClearPinYinSongs", // 按鈕名稱 - clearButtonPinYinCoords, // 按鈕的座標與大小 - buttonImages.normal, // 按鈕的普通狀態圖片 - buttonImages.mouseOver, // 滑鼠懸停時的圖片 - buttonImages.mouseDown, // 滑鼠按下時的圖片 - ClearButtonPinYinSongs_Click // 點擊事件處理函式 + clearButtonPinYinCoords, // 設定按鈕的座標與大小 + buttonImages.normal, // 設定按鈕的正常狀態圖片 + buttonImages.mouseOver, // 設定按鈕的滑鼠懸停圖片 + buttonImages.mouseDown, // 設定按鈕的按下狀態圖片 + ClearButtonPinYinSongs_Click // 綁定按鈕的點擊事件處理函式 ); - } + /// + /// 清空拼音輸入框的內容。 + /// 當使用者點擊清除按鈕時,若輸入框存在且有內容,則將其清空。 + /// private void ClearButtonPinYinSongs_Click(object sender, EventArgs e) { // 檢查視窗內是否包含 inputBoxPinYinSongs 控制項,且輸入框內是否有文字 @@ -193,29 +219,36 @@ namespace DualScreenDemo } } + /// + /// 初始化「關閉」按鈕 (`closeButtonPinYinSongs`),用於隱藏拼音輸入介面。 + /// private void InitializeCloseButtonPinYinSongs() { // 讀取設定檔中的按鈕配置數據 var data = LoadConfigData(); - // 從設定檔中取得「關閉」按鈕的座標 + // 從設定檔中取得「關閉」按鈕的座標 (X, Y, Width, Height) closeButtonPinYinCoords = LoadSpecialButtonCoordinates(data, "SpecialButtonCoordinates", "closeButtonPinYinSongs"); - // 從設定檔中讀取「關閉」按鈕的圖片 + // 從設定檔中讀取「關閉」按鈕的圖片 (一般狀態、滑鼠懸停、按下時的圖片) var buttonImages = LoadButtonImages(data, "CloseButtonImagesPinYin"); - // 建立「關閉」按鈕,並設定名稱、座標、按鈕圖片及點擊事件 + // 建立「關閉」按鈕,設定名稱、座標、圖片及點擊事件 closeButtonPinYinSongs = CreateSpecialButton( - "btnClosePinYinSongs", // 按鈕名稱 - closeButtonPinYinCoords, // 按鈕座標 (X, Y, Width, Height) - buttonImages.normal, // 按鈕的普通狀態圖片 - buttonImages.mouseOver, // 滑鼠懸停時的圖片 - buttonImages.mouseDown, // 按下時的圖片 - CloseButtonPinYinSongs_Click // 點擊事件處理函式 + "btnClosePinYinSongs", // 按鈕名稱 + closeButtonPinYinCoords, // 設定按鈕的座標與大小 + buttonImages.normal, // 設定按鈕的正常狀態圖片 + buttonImages.mouseOver, // 設定按鈕的滑鼠懸停圖片 + buttonImages.mouseDown, // 設定按鈕的按下狀態圖片 + CloseButtonPinYinSongs_Click // 綁定按鈕的點擊事件處理函式 ); - } + /// + /// 關閉拼音輸入模式,隱藏相關 UI 元件。 + /// + /// 觸發事件的按鈕。 + /// 事件參數。 private void CloseButtonPinYinSongs_Click(object sender, EventArgs e) { // 隱藏拼音輸入的背景圖片 (可能是 UI 中的輸入框背景) @@ -224,7 +257,9 @@ namespace DualScreenDemo SetPinYinSongsAndButtonsVisibility(false); } - + /// + /// 初始化拼音輸入框 (`RichTextBox`),並從 `config.ini` 讀取相關設定。 + /// private void InitializeInputBoxPinYinSongs() { try @@ -245,13 +280,13 @@ namespace DualScreenDemo data = parser.ReadData(reader); } - // 從 INI 檔案讀取拼音輸入框的位置與大小 + // **從 INI 檔案讀取拼音輸入框的位置與大小** int x = int.Parse(data["InputBoxPinYinSongs"]["X"]); // X 座標 int y = int.Parse(data["InputBoxPinYinSongs"]["Y"]); // Y 座標 int width = int.Parse(data["InputBoxPinYinSongs"]["Width"]); // 寬度 int height = int.Parse(data["InputBoxPinYinSongs"]["Height"]); // 高度 - // 讀取字型設定 + // **讀取字型設定** string fontName = data["InputBoxPinYinSongs"]["FontName"]; // 字型名稱 float fontSize = float.Parse(data["InputBoxPinYinSongs"]["FontSize"]); // 字體大小 FontStyle fontStyle = (FontStyle)Enum.Parse(typeof(FontStyle), data["InputBoxPinYinSongs"]["FontStyle"]); // 字體樣式 @@ -273,7 +308,7 @@ namespace DualScreenDemo // 設定輸入框的位置與大小 ResizeAndPositionControl(inputBoxPinYinSongs, x, y, width, height); - // 綁定 `TextChanged` 事件 (當輸入內容改變時觸發搜尋) + // **綁定 `TextChanged` 事件 (當輸入內容改變時觸發搜尋)** inputBoxPinYinSongs.TextChanged += (sender, e) => { string searchText = inputBoxPinYinSongs.Text; @@ -298,11 +333,22 @@ namespace DualScreenDemo // 發生錯誤時輸出錯誤訊息 (避免程式崩潰) Console.WriteLine($"An error occurred: {ex.Message}"); } - } - // 讀取 PictureBoxPinYinSongs 的座標設定 + /// + /// 存儲 `PictureBoxPinYinSongs` 的座標與尺寸信息。 + /// + /// + /// 此元組包含以下四個值: + /// X:X 座標 + /// , Y:Y 座標 + /// , Width:寬度 + /// , Height:高度 + /// private (int X, int Y, int Width, int Height) pictureBoxPinYinSongCoords; + /// + /// 從 `config.ini` 配置檔案中載入 `PictureBoxPinYinSongs` 的座標與尺寸設定。 + /// private void LoadPictureBoxPinYinSongCoordsFromConfig() { // 創建一個 INI 檔案解析器 @@ -322,7 +368,10 @@ namespace DualScreenDemo int.Parse(coords["Height"]) // 解析 高度 ); } - // 顯示拼音歌曲圖片 + /// + /// 顯示拼音歌曲圖片 + /// + /// 圖片路徑 private void ShowImageOnPictureBoxPinYinSongs(string imagePath) { // 從設定檔載入 PictureBox 的座標與大小 @@ -355,7 +404,10 @@ namespace DualScreenDemo pictureBoxPinYinSongs.Visible = true; } - // 設定拼音模式的 UI 是否可見 + /// + /// 設定拼音模式的 UI 是否可見 + /// + /// 是否可見 private void SetPinYinSongsAndButtonsVisibility(bool isVisible) { // 定義一個委派 (Action),用於更新 UI 控件的可見性 From 193c78fde8387b97a48f8bd3e0428c68320468ba Mon Sep 17 00:00:00 2001 From: jasonchenwork Date: Wed, 19 Mar 2025 10:35:48 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E6=AD=8C=E6=9B=B2=E6=9F=A5=E8=A9=A2?= =?UTF-8?q?=E4=B8=BB=E9=A0=81=E9=9D=A2=E5=92=8C=E6=95=B8=E5=AD=97=E6=9F=A5?= =?UTF-8?q?=E8=A9=A2=E8=A8=BB=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PrimaryForm.SongSearch.NumberSearch.cs | 199 ++++++++++++------ .../SongSearch/PrimaryForm.SongSearch.cs | 79 +++++-- 2 files changed, 199 insertions(+), 79 deletions(-) diff --git a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.NumberSearch.cs b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.NumberSearch.cs index f7edf9e..64012c3 100644 --- a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.NumberSearch.cs +++ b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.NumberSearch.cs @@ -8,95 +8,138 @@ namespace DualScreenDemo { public partial class PrimaryForm { + /// + /// 「數字搜尋」按鈕點擊事件 + /// 1. 更新所有搜尋按鈕的背景圖片,使「數字搜尋」顯示為啟動狀態 + /// 2. 在 `pictureBoxSongIDSearch` 顯示對應的圖片 + /// 3. 顯示「數字搜尋」相關 UI 元素 + /// private void NumberSearchButton2_Click(object sender, EventArgs e) { + // 更新搜尋按鈕的背景圖片 (將所有按鈕設為未選中狀態,僅數字搜尋為選中狀態) zhuyinSearchSongButton.BackgroundImage = zhuyinSearchSongNormalBackground; englishSearchSongButton.BackgroundImage = englishSearchSongNormalBackground; pinyinSearchSongButton.BackgroundImage = pinyinSearchSongNormalBackground; wordCountSearchSongButton.BackgroundImage = wordCountSearchSongNormalBackground; handWritingSearchSongButton.BackgroundImage = handWritingSearchNormalBackground; - numberSearchSongButton.BackgroundImage = numberSearchSongActiveBackground; + numberSearchSongButton.BackgroundImage = numberSearchSongActiveBackground; // 設定數字搜尋為選中狀態 + // 在 `pictureBoxSongIDSearch` 顯示數字搜尋的 UI 圖片 ShowImageOnPictureBoxSongIDSearch(Path.Combine(Application.StartupPath, @"themes\superstar\6-1.png")); + // 顯示與數字搜尋相關的 UI 元素 SetPictureBoxSongIDSearchAndButtonsVisibility(true); pictureBoxSongIDSearch.Visible = true; } + /// + /// 在 pictureBoxSongIDSearch 中顯示指定路徑的圖片,並對其進行裁切與調整大小 + /// 1. 加載原始圖片 + /// 2. 裁切圖片以符合 UI 需求 + /// 3. 設定 pictureBoxSongIDSearch 的圖片 + /// 4. 調整 pictureBoxSongIDSearch 的位置與大小 + /// 5. 顯示 pictureBoxSongIDSearch + /// + /// 要顯示的圖片路徑 private void ShowImageOnPictureBoxSongIDSearch(string imagePath) { - + // 1. 加載原始圖片 Bitmap originalImage = new Bitmap(imagePath); - + // 2. 定義裁切區域 (左上角 x=593, y=135, 寬=507, 高=508) Rectangle cropArea = new Rectangle(593, 135, 507, 508); - + // 3. 進行圖片裁切 Bitmap croppedImage = CropImage(originalImage, cropArea); - + // 4. 設定 `pictureBoxSongIDSearch` 的圖片 pictureBoxSongIDSearch.Image = croppedImage; - - + + // 5. 調整 `pictureBoxSongIDSearch` 的大小與位置 (基於 cropArea 並加上偏移量) ResizeAndPositionPictureBox(pictureBoxSongIDSearch, cropArea.X + offsetXSongID, cropArea.Y + offsetYSongID, cropArea.Width, cropArea.Height); - + + // 6. 顯示 `pictureBoxSongIDSearch` pictureBoxSongIDSearch.Visible = true; } + + /// + /// 當使用者點擊「修改按鈕」時,刪除 `inputBoxSongIDSearch` 輸入框內的最後一個字元。 + /// + /// 觸發事件的對象(按鈕) + /// 事件參數 private void ModifyButtonSongIDSearch_Click(object sender, EventArgs e) { - + // 確保 `inputBoxSongIDSearch` 內有文字,避免 `Substring` 發生錯誤 if (inputBoxSongIDSearch.Text.Length > 0) { - + // 刪除輸入框內的最後一個字元 inputBoxSongIDSearch.Text = inputBoxSongIDSearch.Text.Substring(0, inputBoxSongIDSearch.Text.Length - 1); } } + + /// + /// 當使用者點擊「關閉按鈕」時,隱藏歌曲編號搜尋的相關 UI 元件。 + /// + /// 觸發事件的對象(按鈕) + /// 事件參數 private void CloseButtonSongIDSearch_Click(object sender, EventArgs e) { - + // 隱藏歌曲編號搜尋的相關 UI 元件(包含輸入框、按鈕、圖片等) SetPictureBoxSongIDSearchAndButtonsVisibility(false); } + /// + /// 控制歌曲編號搜尋的 UI 顯示與隱藏。 + /// true 時,顯示 UI 元件。 + /// false 時,隱藏 UI 元件。 + /// + /// 是否顯示 UI private void SetPictureBoxSongIDSearchAndButtonsVisibility(bool isVisible) { + // 定義 UI 更新的 Action System.Action action = () => { + // 暫停佈局更新,提高效能 SuspendLayout(); - + // 控制歌曲編號搜尋圖片的顯示/隱藏 pictureBoxSongIDSearch.Visible = isVisible; - + // 如果顯示圖片,則將其置頂 if (isVisible) pictureBoxSongIDSearch.BringToFront(); - + // 控制「修改」和「關閉」按鈕的可見性 modifyButtonSongIDSearch.Visible = isVisible; closeButtonSongIDSearch.Visible = isVisible; - + // 如果按鈕顯示,則置頂 if (isVisible) { modifyButtonSongIDSearch.BringToFront(); closeButtonSongIDSearch.BringToFront(); } - + // 控制數字按鈕的可見性 foreach (Button button in numberButtonsSongIDSearch) { button.Visible = isVisible; + // 使按鈕顯示時位於最上層 if (isVisible) button.BringToFront(); } + // 控制輸入框的可見性 inputBoxSongIDSearch.Visible = isVisible; if (isVisible) inputBoxSongIDSearch.BringToFront(); + // 恢復佈局更新 ResumeLayout(); }; + // 如果當前執行緒不是 UI 執行緒,則使用 Invoke 呼叫 if (this.InvokeRequired) { this.Invoke(action); @@ -106,113 +149,140 @@ namespace DualScreenDemo action(); } } + + /// + /// 初始化數字輸入 (Song ID Search) 相關按鈕與輸入框。 + /// 這些按鈕用於數字輸入、刪除 (Modify) 及關閉 (Close) 功能。 + /// private void InitializeButtonsForPictureBoxSongIDSearch() { - + // 數字按鈕的座標陣列 (左上角 X, 左上角 Y, 右下角 X, 右下角 Y) int[,] coords = new int[,] { - {651, 292, 752, 400}, - {760, 292, 861, 400}, - {869, 292, 972, 399}, - {652, 401, 752, 502}, - {760, 401, 861, 504}, - {869, 398, 972, 502}, - {651, 502, 753, 607}, - {759, 504, 863, 607}, - {869, 503, 973, 608}, - {981, 501, 1083, 609} + {651, 292, 752, 400}, // 1 + {760, 292, 861, 400}, // 2 + {869, 292, 972, 399}, // 3 + {652, 401, 752, 502}, // 4 + {760, 401, 861, 504}, // 5 + {869, 398, 972, 502}, // 6 + {651, 502, 753, 607}, // 7 + {759, 504, 863, 607}, // 8 + {869, 503, 973, 608}, // 9 + {981, 501, 1083, 609} // 0 }; + // 取得螢幕的解析度 int screenW = Screen.PrimaryScreen.Bounds.Width; int screenH = Screen.PrimaryScreen.Bounds.Height; - + // 計算畫面縮放比例 float widthRatio = screenW / (float)1920; float heightRatio = screenH / (float)900; + // 初始化數字按鈕陣列 numberButtonsSongIDSearch = new Button[10]; + // 建立數字按鈕 for (int i = 0; i < numberButtonsSongIDSearch.Length; i++) { numberButtonsSongIDSearch[i] = new Button(); - + // 設定按鈕大小與位置 ConfigureButton( numberButtonsSongIDSearch[i], - coords[i, 0], - coords[i, 1], - coords[i, 2] - coords[i, 0], - coords[i, 3] - coords[i, 1], - - resizedNormalStateImageFor6_1, - resizedMouseOverImageFor6_1, - resizedMouseDownImageFor6_1, + coords[i, 0], // X 座標 + coords[i, 1], // Y 座標 + coords[i, 2] - coords[i, 0], // 按鈕寬度 + coords[i, 3] - coords[i, 1], // 按鈕高度 + resizedNormalStateImageFor6_1, // 一般狀態圖片 + resizedMouseOverImageFor6_1, // 滑鼠懸停圖片 + resizedMouseDownImageFor6_1, // 按下時圖片 null ); + // 重新計算按鈕位置,確保適應不同解析度 int newXForSongID = (int)(((numberButtonsSongIDSearch[i].Location.X / widthRatio) + offsetXSongID) * widthRatio); int newYForSongID = (int)(((numberButtonsSongIDSearch[i].Location.Y / heightRatio) + offsetYSongID) * heightRatio); numberButtonsSongIDSearch[i].Location = new Point(newXForSongID, newYForSongID); - + // 設定按鈕名稱與 Tag (數字值) numberButtonsSongIDSearch[i].Name = "NumberButtonSongIDSearch" + i; - numberButtonsSongIDSearch[i].Tag = (i + 1).ToString(); - if (i == 9) + if (i == 9) // 最後一個按鈕 (實際上應為數字 "0") { numberButtonsSongIDSearch[i].Name = "NumberButtonSongIDSearch0"; numberButtonsSongIDSearch[i].Tag = "0"; } - + // 設定按鈕的點擊事件 numberButtonsSongIDSearch[i].Click += SongIDSearchButton_Click; - + // 加入畫面 this.Controls.Add(numberButtonsSongIDSearch[i]); } - - modifyButtonSongIDSearch = new Button { + // 初始化「刪除」按鈕 (Modify) + modifyButtonSongIDSearch = new Button + { Name = "ModifyButtonSongIDSearch", Tag = "Modify", Visible = false }; - ConfigureButton(modifyButtonSongIDSearch, 978, 292, 1081 - 978, 397 - 292, resizedNormalStateImageFor6_1, resizedMouseOverImageFor6_1, resizedMouseDownImageFor6_1, ModifyButtonSongIDSearch_Click); + ConfigureButton(modifyButtonSongIDSearch, 978, 292, 1081 - 978, 397 - 292, + resizedNormalStateImageFor6_1, resizedMouseOverImageFor6_1, resizedMouseDownImageFor6_1, ModifyButtonSongIDSearch_Click); + + // 調整刪除按鈕位置以適應不同解析度 int newX = (int)(((modifyButtonSongIDSearch.Location.X / widthRatio) + offsetXSongID) * widthRatio); - int newY = (int)(((modifyButtonSongIDSearch.Location.Y / widthRatio) + offsetYSongID) * heightRatio); + int newY = (int)(((modifyButtonSongIDSearch.Location.Y / heightRatio) + offsetYSongID) * heightRatio); modifyButtonSongIDSearch.Location = new Point(newX, newY); + this.Controls.Add(modifyButtonSongIDSearch); - - - closeButtonSongIDSearch = new Button { + + // 初始化「關閉」按鈕 (Close) + closeButtonSongIDSearch = new Button + { Name = "CloseButtonSongIDSearch", Tag = "Close", Visible = false }; - - ConfigureButton(closeButtonSongIDSearch, 982, 147, 1082 - 982, 250 - 147, resizedNormalStateImageFor6_1, resizedMouseOverImageFor6_1, resizedMouseDownImageFor6_1, CloseButtonSongIDSearch_Click); + + ConfigureButton(closeButtonSongIDSearch, 982, 147, 1082 - 982, 250 - 147, + resizedNormalStateImageFor6_1, resizedMouseOverImageFor6_1, resizedMouseDownImageFor6_1, CloseButtonSongIDSearch_Click); + + // 調整關閉按鈕位置以適應不同解析度 newX = (int)(((closeButtonSongIDSearch.Location.X / widthRatio) + offsetXSongID) * widthRatio); - newY = (int)(((closeButtonSongIDSearch.Location.Y / widthRatio) + offsetYSongID) * heightRatio); + newY = (int)(((closeButtonSongIDSearch.Location.Y / heightRatio) + offsetYSongID) * heightRatio); closeButtonSongIDSearch.Location = new Point(newX, newY); + this.Controls.Add(closeButtonSongIDSearch); - inputBoxSongIDSearch = new RichTextBox(); - inputBoxSongIDSearch.Name = "inputBoxSongIDSearch"; - ResizeAndPositionControl(inputBoxSongIDSearch, 645 + offsetXSongID, 197 + offsetXSongID, 986 - 645, 281 - 197); - inputBoxSongIDSearch.ForeColor = Color.Black; - inputBoxSongIDSearch.Font = new Font("細明體", (float)26 / 900 * Screen.PrimaryScreen.Bounds.Height, FontStyle.Regular); + // 初始化輸入框 (RichTextBox) + inputBoxSongIDSearch = new RichTextBox + { + Name = "inputBoxSongIDSearch", + ForeColor = Color.Black, + Font = new Font("細明體", (float)26 / 900 * Screen.PrimaryScreen.Bounds.Height, FontStyle.Regular) + }; + // 調整輸入框大小與位置 + ResizeAndPositionControl(inputBoxSongIDSearch, 645 + offsetXSongID, 197 + offsetXSongID, 986 - 645, 281 - 197); + + // 當輸入框內容改變時,自動搜尋歌曲 inputBoxSongIDSearch.TextChanged += (sender, e) => { string searchText = inputBoxSongIDSearch.Text; - + + // 使用 LINQ 搜尋符合條件的歌曲 (以輸入的數字開頭) var searchResults = allSongs.Where(song => song.SongNumber.StartsWith(searchText)).ToList(); + + // 重設分頁與歌曲列表 currentPage = 0; currentSongList = searchResults; totalPages = (int)Math.Ceiling((double)searchResults.Count / itemsPerPage); + // 更新歌曲顯示 multiPagePanel.currentPageIndex = 0; multiPagePanel.LoadSongs(currentSongList); }; @@ -220,16 +290,25 @@ namespace DualScreenDemo this.Controls.Add(inputBoxSongIDSearch); } + + /// + /// 數字按鈕點擊事件,將按鈕上的數字 (Tag 值) 加入到 inputBoxSongIDSearch 中。 + /// + /// 觸發事件的按鈕 + /// 事件參數 private void SongIDSearchButton_Click(object sender, EventArgs e) { - - + // 嘗試將 sender 轉型為 Button var button = sender as Button; + + // 確保按鈕不為 null 且具有 Tag 屬性 (Tag 屬性存放數字) if (button != null && button.Tag != null) { + // 將按鈕的 Tag 值 (數字) 加入到輸入框 inputBoxSongIDSearch.Text += button.Tag.ToString(); } } + } } \ No newline at end of file diff --git a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.cs b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.cs index 37823f2..0f3daaa 100644 --- a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.cs +++ b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.cs @@ -4,9 +4,13 @@ using System.Windows.Forms; namespace DualScreenDemo { - /* 建構子創立,程式進入初始位置,所有搜尋初始化設置 */ + /* + * 主要視窗 (PrimaryForm) 的部分定義 + * 負責初始化搜尋按鈕並處理歌曲搜尋 UI 相關邏輯 + */ public partial class PrimaryForm { + // 各種歌曲搜尋按鈕及其對應的背景圖片 (一般狀態 / 啟動狀態) private Button zhuyinSearchSongButton; private Bitmap zhuyinSearchSongNormalBackground; private Bitmap zhuyinSearchSongActiveBackground; @@ -26,8 +30,15 @@ namespace DualScreenDemo private Bitmap numberSearchSongNormalBackground; private Bitmap numberSearchSongActiveBackground; + /// + /// 點擊「歌曲搜尋」按鈕時的事件處理函式 + /// 1. 更新導航按鈕的背景圖片,使「歌曲搜尋」按鈕顯示為啟動狀態 + /// 2. 隱藏其他搜尋/分類 UI,僅顯示歌曲搜尋選單 + /// 3. 若有 QR Code 顯示,則將其隱藏 + /// private void SongSearchButton_Click(object sender, EventArgs e) { + // 更新導航按鈕的背景圖片 newSongAlertButton.BackgroundImage = newSongAlertNormalBackground; hotPlayButton.BackgroundImage = hotPlayNormalBackground; singerSearchButton.BackgroundImage = singerSearchNormalBackground; @@ -41,7 +52,7 @@ namespace DualScreenDemo deliciousFoodButton.BackgroundImage = deliciousFoodNormalBackground; isOnOrderedSongsPage = false; - + // 隱藏其他 UI SetHotSongButtonsVisibility(false); SetNewSongButtonsVisibility(false); SetSingerSearchButtonsVisibility(false); @@ -51,14 +62,15 @@ namespace DualScreenDemo SetZhuYinSingersAndButtonsVisibility(false); SetZhuYinSongsAndButtonsVisibility(false); SetEnglishSingersAndButtonsVisibility(false); - SetPinYinSingersAndButtonsVisibility(false); SetPinYinSongsAndButtonsVisibility(false); SetPictureBoxToggleLightAndButtonsVisibility(false); SetPictureBoxSceneSoundEffectsAndButtonsVisibility(false); + + // 顯示歌曲搜尋選單按鈕 SetSongSearchButtonsVisibility(true); - + // 隱藏 QR Code (若有) if (pictureBoxQRCode != null) { pictureBoxQRCode.Visible = false; @@ -66,12 +78,25 @@ namespace DualScreenDemo } } + /// + /// 設定「歌曲搜尋」相關按鈕的可見性 + /// + /// 是否顯示 private void SetSongSearchButtonsVisibility(bool isVisible) { - pictureBox4.Visible = isVisible; + pictureBox4.Visible = isVisible; // 控制搜尋 UI 背景的可見性 - Button[] songSearchButtons = { zhuyinSearchSongButton, englishSearchSongButton, wordCountSearchSongButton, pinyinSearchSongButton, handWritingSearchSongButton, numberSearchSongButton }; + // 歌曲搜尋的按鈕陣列 + Button[] songSearchButtons = { + zhuyinSearchSongButton, + englishSearchSongButton, + wordCountSearchSongButton, + pinyinSearchSongButton, + handWritingSearchSongButton, + numberSearchSongButton + }; + // 設定按鈕可見性,若顯示則移至最前 foreach (var button in songSearchButtons) { button.Visible = isVisible; @@ -82,25 +107,41 @@ namespace DualScreenDemo } } + /// + /// 初始化所有「歌曲搜尋」按鈕 + /// 依據不同的搜尋方式 (注音、英文、拼音、筆劃、手寫、數字) 建立對應按鈕 + /// private void InitializeButtonsForSongSearch() { - - InitializeSearchButton(ref zhuyinSearchSongButton, "zhuyinSearchSongButton", 1214, 230, 209, 59, ref zhuyinSearchSongNormalBackground, ref zhuyinSearchSongActiveBackground, normalStateImageSongQuery, mouseDownImageSongQuery, ZhuyinSearchSongsButton_Click); + // 初始化「注音搜尋」按鈕 + InitializeSearchButton(ref zhuyinSearchSongButton, "zhuyinSearchSongButton", + 1214, 230, 209, 59, ref zhuyinSearchSongNormalBackground, ref zhuyinSearchSongActiveBackground, + normalStateImageSongQuery, mouseDownImageSongQuery, ZhuyinSearchSongsButton_Click); - - InitializeSearchButton(ref englishSearchSongButton, "englishSearchSongButton", 1214, 293, 209, 58, ref englishSearchSongNormalBackground, ref englishSearchSongActiveBackground, normalStateImageSongQuery, mouseDownImageSongQuery, EnglishSearchSongsButton_Click); + // 初始化「英文搜尋」按鈕 + InitializeSearchButton(ref englishSearchSongButton, "englishSearchSongButton", + 1214, 293, 209, 58, ref englishSearchSongNormalBackground, ref englishSearchSongActiveBackground, + normalStateImageSongQuery, mouseDownImageSongQuery, EnglishSearchSongsButton_Click); - - InitializeSearchButton(ref pinyinSearchSongButton, "pinyinSearchSongButton", 1214, 356, 209, 58, ref pinyinSearchSongNormalBackground, ref pinyinSearchSongActiveBackground, normalStateImageSongQuery, mouseDownImageSongQuery, PinyinSearchSongsButton_Click); + // 初始化「拼音搜尋」按鈕 + InitializeSearchButton(ref pinyinSearchSongButton, "pinyinSearchSongButton", + 1214, 356, 209, 58, ref pinyinSearchSongNormalBackground, ref pinyinSearchSongActiveBackground, + normalStateImageSongQuery, mouseDownImageSongQuery, PinyinSearchSongsButton_Click); - - InitializeSearchButton(ref wordCountSearchSongButton, "wordCountSearchSongButton", 1214, 418, 209, 59, ref wordCountSearchSongNormalBackground, ref wordCountSearchSongActiveBackground, normalStateImageSongQuery, mouseDownImageSongQuery, WordCountSearchSong_Click); + // 初始化「筆劃搜尋」按鈕 + InitializeSearchButton(ref wordCountSearchSongButton, "wordCountSearchSongButton", + 1214, 418, 209, 59, ref wordCountSearchSongNormalBackground, ref wordCountSearchSongActiveBackground, + normalStateImageSongQuery, mouseDownImageSongQuery, WordCountSearchSong_Click); - - InitializeSearchButton(ref handWritingSearchSongButton, "handWritingSearchSongButton", 1214, 481, 209, 59, ref handWritingSearchSongNormalBackground, ref handWritingSearchSongActiveBackground, normalStateImageSongQuery, mouseDownImageSongQuery, HandWritingSearchButtonForSongs_Click); + // 初始化「手寫搜尋」按鈕 + InitializeSearchButton(ref handWritingSearchSongButton, "handWritingSearchSongButton", + 1214, 481, 209, 59, ref handWritingSearchSongNormalBackground, ref handWritingSearchSongActiveBackground, + normalStateImageSongQuery, mouseDownImageSongQuery, HandWritingSearchButtonForSongs_Click); - - InitializeSearchButton(ref numberSearchSongButton, "numberSearchSongButton", 1214, 544, 209, 58, ref numberSearchSongNormalBackground, ref numberSearchSongActiveBackground, normalStateImageSongQuery, mouseDownImageSongQuery, NumberSearchButton2_Click); + // 初始化「數字搜尋」按鈕 + InitializeSearchButton(ref numberSearchSongButton, "numberSearchSongButton", + 1214, 544, 209, 58, ref numberSearchSongNormalBackground, ref numberSearchSongActiveBackground, + normalStateImageSongQuery, mouseDownImageSongQuery, NumberSearchButton2_Click); } } -} \ No newline at end of file +} From 00f019f1b5e748ac300a81bd9a9ae0dea0324772 Mon Sep 17 00:00:00 2001 From: jasonchenwork Date: Wed, 19 Mar 2025 11:07:59 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E6=AD=8C=E6=9B=B2=E6=9F=A5=E8=A9=A2?= =?UTF-8?q?=E6=B3=A8=E9=9F=B3=E8=A8=BB=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PrimaryForm.SongSearch.BopomofoSearch.cs | 309 ++++++++++++++---- .../PrimaryForm.SongSearch.PinyinSearch.cs | 58 ++-- 2 files changed, 274 insertions(+), 93 deletions(-) diff --git a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.BopomofoSearch.cs b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.BopomofoSearch.cs index dcae270..12d459c 100644 --- a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.BopomofoSearch.cs +++ b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.BopomofoSearch.cs @@ -13,16 +13,22 @@ namespace DualScreenDemo { public partial class PrimaryForm { + // 注音歌曲的 PictureBox private PictureBox pictureBoxZhuYinSongs; - + //存放注音按鈕的陣列 private Button[] phoneticButtonsForSongs; + //特殊功能按鈕(修改、清除、關閉) private Button modifyButtonZhuYinSongs; private Button clearButtonZhuYinSongs; private Button closeButtonZhuYinSongs; + //用於顯示輸入文字的輸入框 private RichTextBox inputBoxZhuYinSongs; - + /// + /// 注音歌曲搜尋按鈕點擊事件 + /// private void ZhuyinSearchSongsButton_Click(object sender, EventArgs e) { + //更新搜尋模式按鈕的背景圖 zhuyinSearchSongButton.BackgroundImage = zhuyinSearchSongActiveBackground; englishSearchSongButton.BackgroundImage = englishSearchSongNormalBackground; pinyinSearchSongButton.BackgroundImage = pinyinSearchSongNormalBackground; @@ -30,199 +36,318 @@ namespace DualScreenDemo handWritingSearchSongButton.BackgroundImage = handWritingSearchSongNormalBackground; numberSearchSongButton.BackgroundImage = numberSearchSongNormalBackground; - + // 讀取 config.ini 並獲取注音圖片的路徑 var configData = LoadConfigData(); - /* 抓注音圖檔(ZhuYinSongs) 來自configData的資料 */ - /* 要確認路經需確認configData內容值 */ string imagePath = Path.Combine(Application.StartupPath, configData["ImagePaths"]["ZhuYinSongs"]); - + //顯示注音歌曲圖片 ShowImageOnPictureBoxZhuYinSongs(Path.Combine(Application.StartupPath, imagePath)); - - SetZhuYinSingersAndButtonsVisibility(false); + //設定不同模式的UI顯示 + //SetZhuYinSingersAndButtonsVisibility(false); SetEnglishSingersAndButtonsVisibility(false); SetPinYinSingersAndButtonsVisibility(false); SetHandWritingForSingersAndButtonsVisibility(false); SetZhuYinSongsAndButtonsVisibility(true); pictureBoxZhuYinSongs.Visible = true; } - /* 初始化拼音按鈕 */ + /// + /// 初始化注音按鈕 (Phonetic Buttons) 並載入其對應的圖片與座標 + /// 1. 讀取 config.ini 設定檔,獲取按鈕的相關數據 (符號、座標、圖片) + /// 2. 解析注音符號並儲存至 phoneticSymbols 陣列 + /// 3. 解析按鈕的座標資訊,存入 phoneticButtonCoords + /// 4. 解析按鈕的圖片 (正常狀態、按下狀態、懸停狀態),存入 phoneticButtonImages。 + /// 5. 依序建立 35 個注音按鈕,並套用對應的圖片與事件處理函數。 + /// private void InitializePhoneticButtonsForSongs() { + // 1. 從設定檔 (config.ini) 讀取配置數據,包含按鈕座標、圖片等 var data = LoadConfigData(); + // 2. 讀取注音符號列表,這些符號將用於顯示在按鈕上 phoneticSymbols = LoadPhoneticSymbols(data); + + // 3. 從設定檔載入 **注音按鈕的座標**,每個按鈕都有對應的 (X, Y, Width, Height) phoneticButtonCoords = LoadButtonCoordinates(data, "PhoneticButtonCoordinates", 35); + + // 4. 從設定檔載入 **注音按鈕的圖片**,每個按鈕都有正常、按下、懸停三種狀態 phoneticButtonImages = LoadButtonImages(data, "PhoneticButtonImages", 35); + // 5. 建立 35 個注音按鈕的陣列 (每個按鈕對應一個注音符號) phoneticButtonsForSongs = new Button[35]; + + // 6. 迴圈建立所有的注音按鈕 for (int i = 0; i < 35; i++) { + // 取得當前按鈕的圖片 (從已載入的 phoneticButtonImages 字典中獲取) var buttonImages = phoneticButtonImages[$"button{i}"]; - CreatePhoneticButtonForSongs(i, buttonImages.normal, buttonImages.mouseDown, buttonImages.mouseOver); + + // 建立單個注音按鈕,並設定其圖片與點擊事件 + CreatePhoneticButtonForSongs( + i, // 按鈕索引 (對應於 phoneticSymbols) + buttonImages.normal, // 按鈕的普通狀態圖片 + buttonImages.mouseDown, // 按下時的圖片 + buttonImages.mouseOver // 滑鼠懸停時的圖片 + ); } } - /* 按鈕設置顯示方式 可參考按鈕事件寫法 */ + + + /// + /// 建立單個注音按鈕,並設定其圖片、大小、位置,以及滑鼠事件。 + /// + /// 按鈕索引 (對應於 phoneticSymbols) + /// 按鈕的普通狀態圖片路徑 + /// 按鈕被按下時的圖片路徑 + /// 滑鼠懸停時的圖片路徑 private void CreatePhoneticButtonForSongs(int index, string normalImagePath, string mouseDownImagePath, string mouseOverImagePath) { try { - - + // 1. 創建按鈕並初始化屬性 phoneticButtonsForSongs[index] = new Button { - Name = $"phoneticButton_{phoneticSymbols[index]}", - BackgroundImage = Image.FromFile(Path.Combine(Application.StartupPath, normalImagePath)), - BackgroundImageLayout = ImageLayout.Stretch, - FlatStyle = FlatStyle.Flat, - FlatAppearance = { BorderSize = 0 } + Name = $"phoneticButton_{phoneticSymbols[index]}", // 設定按鈕名稱,方便識別 + BackgroundImage = Image.FromFile(Path.Combine(Application.StartupPath, normalImagePath)), // 設定預設背景圖 + BackgroundImageLayout = ImageLayout.Stretch, // 背景圖自動填滿按鈕 + FlatStyle = FlatStyle.Flat, // 設定按鈕為扁平樣式 + FlatAppearance = { BorderSize = 0 } // 移除按鈕的邊框 }; - ResizeAndPositionButton(phoneticButtonsForSongs[index], phoneticButtonCoords[index].X, phoneticButtonCoords[index].Y, - phoneticButtonCoords[index].Width, phoneticButtonCoords[index].Height); + // 2. 設定按鈕的大小與位置 + ResizeAndPositionButton( + phoneticButtonsForSongs[index], + phoneticButtonCoords[index].X, + phoneticButtonCoords[index].Y, + phoneticButtonCoords[index].Width, + phoneticButtonCoords[index].Height + ); + // 3. 載入三種狀態的圖片 Image normalImage = Image.FromFile(Path.Combine(Application.StartupPath, normalImagePath)); Image mouseDownImage = Image.FromFile(Path.Combine(Application.StartupPath, mouseDownImagePath)); Image mouseOverImage = Image.FromFile(Path.Combine(Application.StartupPath, mouseOverImagePath)); + // 4. 設定滑鼠事件,改變背景圖 phoneticButtonsForSongs[index].MouseDown += (s, e) => phoneticButtonsForSongs[index].BackgroundImage = mouseDownImage; phoneticButtonsForSongs[index].MouseUp += (s, e) => phoneticButtonsForSongs[index].BackgroundImage = normalImage; phoneticButtonsForSongs[index].MouseEnter += (s, e) => phoneticButtonsForSongs[index].BackgroundImage = mouseOverImage; phoneticButtonsForSongs[index].MouseLeave += (s, e) => phoneticButtonsForSongs[index].BackgroundImage = normalImage; + + // 5. 設定按鈕的點擊事件 (當按下按鈕時,觸發 PhoneticButton_Click) phoneticButtonsForSongs[index].Click += PhoneticButton_Click; + + // 6. 存入對應的注音符號,方便之後的處理 phoneticButtonsForSongs[index].Tag = phoneticSymbols[index]; + // 7. 將按鈕加入視窗 this.Controls.Add(phoneticButtonsForSongs[index]); - - } catch (Exception ex) { + // 例外處理,確保按鈕建立失敗時不影響其他部分 Console.WriteLine($"Error creating button at index {index}: {ex.Message}"); } } + + /// + /// 初始化注音輸入界面的所有按鈕和輸入框。 + /// private void InitializeButtonsForZhuYinSongs() { + // 1. 從設定檔 (config.ini) 載入注音符號 LoadPhoneticSymbolsFromConfig(); + + // 2. 初始化 35 個注音按鈕 InitializePhoneticButtonsForSongs(); + + // 3. 初始化特殊按鈕 (例如:刪除、確定、返回按鈕) InitializeSpecialButtonsForZhuYinSongs(); + + // 4. 初始化輸入框 (用於顯示使用者輸入的注音符號) InitializeInputBoxZhuYinSongs(); } + + /// + /// 初始化注音輸入界面的特殊按鈕,包括「修改」、「清除」和「關閉」。 + /// private void InitializeSpecialButtonsForZhuYinSongs() { - + // 1. 初始化「修改」按鈕 (刪除上一個輸入的注音符號) InitializeModifyButtonZhuYinSongs(); - + // 2. 初始化「清除」按鈕 (清空所有輸入內容) InitializeClearButtonZhuYinSongs(); - + // 3. 初始化「關閉」按鈕 (關閉注音輸入介面) InitializeCloseButtonZhuYinSongs(); } + + /// + /// 初始化「修改」按鈕,讓使用者可以刪除上一個輸入的注音符號。 + /// private void InitializeModifyButtonZhuYinSongs() { + // 1. 讀取設定檔 (config.ini) 來獲取特殊按鈕的座標與圖像資訊 var data = LoadConfigData(); + + // 2. 從設定檔讀取「修改」按鈕的座標數據 modifyButtonZhuYinCoords = LoadSpecialButtonCoordinates(data, "SpecialButtonCoordinates", "modifyButtonZhuYinSongs"); + + // 3. 從設定檔讀取「修改」按鈕的圖像 (Normal、MouseOver、MouseDown) var buttonImages = LoadButtonImages(data, "ModifyButtonImagesZhuYin"); + // 4. 使用座標與圖像來建立「修改」按鈕,並綁定點擊事件 modifyButtonZhuYinSongs = CreateSpecialButton( - "btnModifyZhuYinSongs", - modifyButtonZhuYinCoords, - buttonImages.normal, - buttonImages.mouseOver, - buttonImages.mouseDown, - ModifyButtonZhuYinSongs_Click + "btnModifyZhuYinSongs", // 按鈕名稱 + modifyButtonZhuYinCoords, // 按鈕座標 + buttonImages.normal, // 預設 (normal) 圖像 + buttonImages.mouseOver, // 滑鼠移過 (hover) 圖像 + buttonImages.mouseDown, // 按下 (pressed) 圖像 + ModifyButtonZhuYinSongs_Click // 綁定按鈕點擊事件 ); } + + /// + /// 「修改」按鈕的點擊事件,刪除輸入框內的最後一個注音符號。 + /// private void ModifyButtonZhuYinSongs_Click(object sender, EventArgs e) { - + // 1. 確保輸入框 (inputBoxZhuYinSongs) 存在於目前的視窗控制項中 if (this.Controls.Contains(inputBoxZhuYinSongs) && inputBoxZhuYinSongs.Text.Length > 0) { + // 2. 刪除輸入框中的最後一個字元 (即移除最後一個注音符號) inputBoxZhuYinSongs.Text = inputBoxZhuYinSongs.Text.Substring(0, inputBoxZhuYinSongs.Text.Length - 1); } } + /// + /// 初始化「清除」按鈕,並從設定檔載入其位置與圖片資源。 + /// private void InitializeClearButtonZhuYinSongs() { + // 1. 從設定檔 (config.ini) 讀取配置數據 var data = LoadConfigData(); + + // 2. 讀取「清除」按鈕的座標設定 (從 "SpecialButtonCoordinates" 內的 "clearButtonZhuYinSongs" 取得) clearButtonZhuYinCoords = LoadSpecialButtonCoordinates(data, "SpecialButtonCoordinates", "clearButtonZhuYinSongs"); + + // 3. 讀取「清除」按鈕的圖片 (正常、滑鼠懸停、按下狀態) var buttonImages = LoadButtonImages(data, "ClearButtonImagesZhuYin"); + // 4. 建立「清除」按鈕,並設定對應的事件處理函式 (ClearButtonZhuYinSongs_Click) clearButtonZhuYinSongs = CreateSpecialButton( - "btnClearZhuYinSongs", - clearButtonZhuYinCoords, - buttonImages.normal, - buttonImages.mouseOver, - buttonImages.mouseDown, - ClearButtonZhuYinSongs_Click + "btnClearZhuYinSongs", // 按鈕名稱 + clearButtonZhuYinCoords, // 按鈕座標與大小 + buttonImages.normal, // 正常狀態圖片 + buttonImages.mouseOver, // 滑鼠懸停圖片 + buttonImages.mouseDown, // 按下時圖片 + ClearButtonZhuYinSongs_Click // 點擊事件處理函式 ); } + /// + /// 當使用者點擊「清除」按鈕時,將輸入框 (inputBoxZhuYinSongs) 的內容清空。 + /// + /// 觸發事件的按鈕。 + /// 事件參數。 private void ClearButtonZhuYinSongs_Click(object sender, EventArgs e) - { + { + // 1. 確保視窗內包含「注音輸入框」(inputBoxZhuYinSongs),且輸入框內有文字 if (this.Controls.Contains(inputBoxZhuYinSongs) && inputBoxZhuYinSongs.Text.Length > 0) { + // 2. 清空輸入框內容 inputBoxZhuYinSongs.Text = ""; } } + + /// + /// 初始化注音輸入的關閉按鈕,從設定檔讀取按鈕座標與圖片,並設置點擊事件 + /// private void InitializeCloseButtonZhuYinSongs() { + // 讀取設定檔數據 var data = LoadConfigData(); + + // 從設定檔讀取關閉按鈕的座標 closeButtonZhuYinCoords = LoadSpecialButtonCoordinates(data, "SpecialButtonCoordinates", "closeButtonZhuYinSongs"); + + // 從設定檔讀取關閉按鈕的圖片 var buttonImages = LoadButtonImages(data, "CloseButtonImagesZhuYin"); + // 創建關閉按鈕並綁定點擊事件 closeButtonZhuYinSongs = CreateSpecialButton( - "btnCloseZhuYinSongs", - closeButtonZhuYinCoords, - buttonImages.normal, - buttonImages.mouseOver, - buttonImages.mouseDown, - CloseButtonZhuYinSongs_Click + "btnCloseZhuYinSongs", // 按鈕名稱 + closeButtonZhuYinCoords, // 按鈕座標 + buttonImages.normal, // 正常狀態圖片 + buttonImages.mouseOver, // 滑鼠懸停圖片 + buttonImages.mouseDown, // 按下圖片 + CloseButtonZhuYinSongs_Click // 綁定點擊事件 ); } + + /// + /// 關閉注音輸入介面,隱藏相關 UI 元件 + /// + /// 觸發事件的按鈕 (關閉按鈕) + /// 事件參數 private void CloseButtonZhuYinSongs_Click(object sender, EventArgs e) { + // 隱藏注音輸入的圖片 pictureBoxZhuYinSongs.Visible = false; + + // 隱藏注音輸入的所有按鈕與介面元素 SetZhuYinSongsAndButtonsVisibility(false); } + /// + /// 初始化注音輸入框 (RichTextBox),設定外觀、事件處理及位置大小 + /// private void InitializeInputBoxZhuYinSongs() { try { + // 讀取輸入框的配置,例如字體、顏色、大小等 LoadInputBoxConfig(); + // 建立注音輸入框並套用讀取到的設定 inputBoxZhuYinSongs = new RichTextBox { Name = "inputBoxZhuYinSongs", - ForeColor = inputBoxForeColor, - Font = new Font(inputBoxFontName, inputBoxFontSize, inputBoxFontStyle), - ScrollBars = RichTextBoxScrollBars.None + ForeColor = inputBoxForeColor, // 設定文字顏色 + Font = new Font(inputBoxFontName, inputBoxFontSize, inputBoxFontStyle), // 設定字體 + ScrollBars = RichTextBoxScrollBars.None // 禁用滾動條 }; - ResizeAndPositionControl(inputBoxZhuYinSongs, inputBoxZhuYinCoords.X, inputBoxZhuYinCoords.Y, inputBoxZhuYinCoords.Width, inputBoxZhuYinCoords.Height); + // 調整輸入框大小與位置 + ResizeAndPositionControl(inputBoxZhuYinSongs, inputBoxZhuYinCoords.X, inputBoxZhuYinCoords.Y, + inputBoxZhuYinCoords.Width, inputBoxZhuYinCoords.Height); + // 設定文字變更事件,用來即時篩選歌曲 inputBoxZhuYinSongs.TextChanged += (sender, e) => { - /* 搜尋結果顯示到前歌單點選 */ - string searchText = inputBoxZhuYinSongs.Text; + string searchText = inputBoxZhuYinSongs.Text; // 取得輸入內容 + + // 根據輸入的注音篩選歌曲清單 var searchResults = allSongs.Where(song => song.PhoneticNotation.StartsWith(searchText)).ToList(); + + // 重置分頁 currentPage = 0; currentSongList = searchResults; totalPages = (int)Math.Ceiling((double)searchResults.Count / itemsPerPage); + // 更新多頁面面板的內容 multiPagePanel.currentPageIndex = 0; multiPagePanel.LoadSongs(currentSongList); }; + // 將輸入框加入到 UI 控制項 this.Controls.Add(inputBoxZhuYinSongs); } catch (Exception ex) @@ -230,51 +355,95 @@ namespace DualScreenDemo Console.WriteLine("Error initializing inputBoxZhuYinSongs: " + ex.Message); } } - + + /// + /// 存儲 PictureBoxZhuYinSongs 的座標與尺寸信息。 + /// + /// + /// 此元組包含以下四個值: + /// X:X 座標 + /// , Y:Y 座標 + /// , Width:寬度 + /// , Height:高度 + /// private (int X, int Y, int Width, int Height) pictureBoxZhuYinSongCoords; + /// + /// 從設定檔 (config.ini) 讀取 PictureBoxZhuYinSongs 的座標與尺寸 + /// private void LoadPictureBoxZhuYinSongCoordsFromConfig() { + // 建立 INI 檔案解析器 var parser = new FileIniDataParser(); + + // 讀取 config.ini 設定檔的內容 IniData data = parser.ReadFile("config.ini"); + // 取得 "PictureBoxZhuYinSongs" 段落的設定數據 var coords = data["PictureBoxZhuYinSongs"]; + + // 解析座標與尺寸,並存入 pictureBoxZhuYinSongCoords pictureBoxZhuYinSongCoords = ( - int.Parse(coords["X"]), - int.Parse(coords["Y"]), - int.Parse(coords["Width"]), - int.Parse(coords["Height"]) + int.Parse(coords["X"]), // 讀取 X 座標 + int.Parse(coords["Y"]), // 讀取 Y 座標 + int.Parse(coords["Width"]), // 讀取寬度 + int.Parse(coords["Height"]) // 讀取高度 ); } + + /// + /// 在 pictureBoxZhuYinSongs 上顯示指定路徑的圖片,並根據設定調整其大小與位置。 + /// + /// 要顯示的圖片檔案路徑 private void ShowImageOnPictureBoxZhuYinSongs(string imagePath) { - + // 從 config.ini 讀取 PictureBox 的座標與尺寸 LoadPictureBoxZhuYinSongCoordsFromConfig(); - + // 讀取圖片檔案並載入 Bitmap 物件 Bitmap originalImage = new Bitmap(imagePath); - - Rectangle displayArea = new Rectangle(pictureBoxZhuYinSongCoords.X, pictureBoxZhuYinSongCoords.Y, pictureBoxZhuYinSongCoords.Width, pictureBoxZhuYinSongCoords.Height); + // 設定圖片顯示區域,使用從設定檔讀取的座標與尺寸 + Rectangle displayArea = new Rectangle( + pictureBoxZhuYinSongCoords.X, + pictureBoxZhuYinSongCoords.Y, + pictureBoxZhuYinSongCoords.Width, + pictureBoxZhuYinSongCoords.Height + ); - + // 設定 PictureBox 的圖片 pictureBoxZhuYinSongs.Image = originalImage; - - ResizeAndPositionPictureBox(pictureBoxZhuYinSongs, displayArea.X, displayArea.Y, displayArea.Width, displayArea.Height); + // 調整 PictureBox 的大小與位置,使其符合設定 + ResizeAndPositionPictureBox( + pictureBoxZhuYinSongs, + displayArea.X, + displayArea.Y, + displayArea.Width, + displayArea.Height + ); + // 顯示 PictureBox pictureBoxZhuYinSongs.Visible = true; } + + /// + /// 設定注音歌曲相關的 PictureBox、按鈕和輸入框的可見性。 + /// + /// 若為 true,則顯示這些控件;否則隱藏。 private void SetZhuYinSongsAndButtonsVisibility(bool isVisible) { + // 定義要執行的操作,設定各控件的可見性 System.Action action = () => { try { + // 暫停佈局邏輯,防止在調整控件可見性時觸發不必要的佈局計算,提升性能 SuspendLayout(); + // 檢查並設定 pictureBoxZhuYinSongs 的可見性 if (pictureBoxZhuYinSongs == null) { Console.WriteLine("pictureBoxZhuYinSongs is null"); @@ -285,6 +454,7 @@ namespace DualScreenDemo if (isVisible) pictureBoxZhuYinSongs.BringToFront(); } + // 檢查並設定 phoneticButtonsForSongs 陣列中每個按鈕的可見性 if (phoneticButtonsForSongs == null) { Console.WriteLine("phoneticButtonsForSongs is null"); @@ -305,6 +475,7 @@ namespace DualScreenDemo } } + // 檢查並設定 modifyButtonZhuYinSongs 的可見性 if (modifyButtonZhuYinSongs == null) { Console.WriteLine("modifyButtonZhuYinSongs is null"); @@ -315,6 +486,7 @@ namespace DualScreenDemo if (isVisible) modifyButtonZhuYinSongs.BringToFront(); } + // 檢查並設定 clearButtonZhuYinSongs 的可見性 if (clearButtonZhuYinSongs == null) { Console.WriteLine("clearButtonZhuYinSongs is null"); @@ -325,6 +497,7 @@ namespace DualScreenDemo if (isVisible) clearButtonZhuYinSongs.BringToFront(); } + // 檢查並設定 closeButtonZhuYinSongs 的可見性 if (closeButtonZhuYinSongs == null) { Console.WriteLine("closeButtonZhuYinSongs is null"); @@ -335,6 +508,7 @@ namespace DualScreenDemo if (isVisible) closeButtonZhuYinSongs.BringToFront(); } + // 檢查並設定 inputBoxZhuYinSongs 的可見性 if (inputBoxZhuYinSongs == null) { Console.WriteLine("inputBoxZhuYinSongs is null"); @@ -345,10 +519,12 @@ namespace DualScreenDemo if (isVisible) inputBoxZhuYinSongs.BringToFront(); } + // 恢復佈局邏輯,允許佈局計算 ResumeLayout(); - PerformLayout(); + // 強制控件立即執行佈局邏輯,確保佈局更新立即生效 + PerformLayout(); - + // 刷新各控件,確保其狀態立即更新 pictureBoxZhuYinSongs?.Refresh(); if (phoneticButtonsForSongs != null) { @@ -364,10 +540,12 @@ namespace DualScreenDemo } catch (Exception ex) { + // 捕捉並輸出異常資訊,方便除錯 Console.WriteLine("Error in SetZhuYinSongsAndButtonsVisibility: " + ex.Message); } }; + // 如果當前執行緒需要呼叫 Invoke 方法才能修改控件,則使用 Invoke if (this.InvokeRequired) { this.Invoke(action); @@ -377,5 +555,6 @@ namespace DualScreenDemo action(); } } + } } \ No newline at end of file diff --git a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.PinyinSearch.cs b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.PinyinSearch.cs index 5a0d7f5..d406e69 100644 --- a/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.PinyinSearch.cs +++ b/PrimaryFormParts/SongSearch/PrimaryForm.SongSearch.PinyinSearch.cs @@ -20,7 +20,9 @@ namespace DualScreenDemo private Button closeButtonPinYinSongs; // 用於顯示輸入文字的輸入框 private RichTextBox inputBoxPinYinSongs; - // 拼音歌曲搜尋按鈕點擊事件 + /// + /// 拼音歌曲搜尋按鈕點擊事件 + /// private void PinyinSearchSongsButton_Click(object sender, EventArgs e) { // 更新搜尋模式按鈕的背景圖 @@ -124,9 +126,9 @@ namespace DualScreenDemo /// /// 初始化拼音輸入的特殊功能按鈕,包括: - /// 1. 修改按鈕 - 刪除輸入框中的最後一個字母 - /// 2. 清除按鈕 - 清空輸入框的內容 - /// 3. 關閉按鈕 - 隱藏拼音輸入的 UI 元件 + /// 1. 修改按鈕 - 刪除輸入框中的最後一個字母 + /// 2. 清除按鈕 - 清空輸入框的內容 + /// 3. 關閉按鈕 - 隱藏拼音輸入的 UI 元件 /// private void InitializeSpecialButtonsForPinYinSongs() { @@ -167,11 +169,11 @@ namespace DualScreenDemo } /// - /// 「修改」按鈕點擊事件:刪除拼音輸入框 (`inputBoxPinYinSongs`) 中的最後一個字母。 + /// 「修改」按鈕點擊事件:刪除拼音輸入框 (inputBoxPinYinSongs) 中的最後一個字母。 /// private void ModifyButtonPinYinSongs_Click(object sender, EventArgs e) { - // 確保 `inputBoxPinYinSongs` 存在於視窗控制項集合內,且輸入框內有文字 + // 確保 inputBoxPinYinSongs 存在於視窗控制項集合內,且輸入框內有文字 if (this.Controls.Contains(inputBoxPinYinSongs) && inputBoxPinYinSongs.Text.Length > 0) { // 刪除輸入框內的最後一個字母 @@ -181,7 +183,7 @@ namespace DualScreenDemo /// - /// 初始化「清除」按鈕 (`clearButtonPinYinSongs`),用於清空拼音輸入框 (`inputBoxPinYinSongs`)。 + /// 初始化「清除」按鈕 (clearButtonPinYinSongs),用於清空拼音輸入框 (inputBoxPinYinSongs)。 /// private void InitializeClearButtonPinYinSongs() { @@ -220,7 +222,7 @@ namespace DualScreenDemo } /// - /// 初始化「關閉」按鈕 (`closeButtonPinYinSongs`),用於隱藏拼音輸入介面。 + /// 初始化「關閉」按鈕 (closeButtonPinYinSongs),用於隱藏拼音輸入介面。 /// private void InitializeCloseButtonPinYinSongs() { @@ -258,7 +260,7 @@ namespace DualScreenDemo } /// - /// 初始化拼音輸入框 (`RichTextBox`),並從 `config.ini` 讀取相關設定。 + /// 初始化拼音輸入框 (RichTextBox),並從 config.ini 讀取相關設定。 /// private void InitializeInputBoxPinYinSongs() { @@ -268,13 +270,13 @@ namespace DualScreenDemo var parser = new FileIniDataParser(); // 配置解析器的參數 - parser.Parser.Configuration.AssigmentSpacer = ""; // 設定 `=` 兩側沒有空格 - parser.Parser.Configuration.CommentString = "#"; // 使用 `#` 作為註解符號 + parser.Parser.Configuration.AssigmentSpacer = ""; // 設定 = 兩側沒有空格 + parser.Parser.Configuration.CommentString = "#"; // 使用 # 作為註解符號 parser.Parser.Configuration.CaseInsensitive = true; // 參數名稱不區分大小寫 IniData data; // 儲存解析後的 INI 數據 - // 讀取 `config.ini` 文件,使用 UTF-8 編碼 + // 讀取 config.ini 文件,使用 UTF-8 編碼 using (var reader = new StreamReader("config.ini", System.Text.Encoding.UTF8)) { data = parser.ReadData(reader); @@ -292,7 +294,7 @@ namespace DualScreenDemo FontStyle fontStyle = (FontStyle)Enum.Parse(typeof(FontStyle), data["InputBoxPinYinSongs"]["FontStyle"]); // 字體樣式 Color foreColor = Color.FromName(data["InputBoxPinYinSongs"]["ForeColor"]); // 文字顏色 - // 創建拼音輸入框 (`RichTextBox`) + // 創建拼音輸入框 (RichTextBox) inputBoxPinYinSongs = new RichTextBox { Visible = false, // 預設為隱藏 @@ -308,7 +310,7 @@ namespace DualScreenDemo // 設定輸入框的位置與大小 ResizeAndPositionControl(inputBoxPinYinSongs, x, y, width, height); - // **綁定 `TextChanged` 事件 (當輸入內容改變時觸發搜尋)** + // **綁定 TextChanged 事件 (當輸入內容改變時觸發搜尋)** inputBoxPinYinSongs.TextChanged += (sender, e) => { string searchText = inputBoxPinYinSongs.Text; @@ -335,7 +337,7 @@ namespace DualScreenDemo } } /// - /// 存儲 `PictureBoxPinYinSongs` 的座標與尺寸信息。 + /// 存儲 PictureBoxPinYinSongs 的座標與尺寸信息。 /// /// /// 此元組包含以下四個值: @@ -347,20 +349,20 @@ namespace DualScreenDemo private (int X, int Y, int Width, int Height) pictureBoxPinYinSongCoords; /// - /// 從 `config.ini` 配置檔案中載入 `PictureBoxPinYinSongs` 的座標與尺寸設定。 + /// 從 config.ini 配置檔案中載入 PictureBoxPinYinSongs 的座標與尺寸設定。 /// private void LoadPictureBoxPinYinSongCoordsFromConfig() { // 創建一個 INI 檔案解析器 var parser = new FileIniDataParser(); - // 讀取 `config.ini` 文件並解析成 `IniData` 對象 + // 讀取 config.ini 文件並解析成 IniData 對象 IniData data = parser.ReadFile("config.ini"); - // 取得 `PictureBoxPinYinSongs` 區段的設定值 + // 取得 PictureBoxPinYinSongs 區段的設定值 var coords = data["PictureBoxPinYinSongs"]; - // 解析 `X`, `Y`, `Width`, `Height`,並存入 `pictureBoxPinYinSongCoords` + // 解析 X, Y, Width, Height,並存入 pictureBoxPinYinSongCoords pictureBoxPinYinSongCoords = ( int.Parse(coords["X"]), // 解析 X 座標 int.Parse(coords["Y"]), // 解析 Y 座標 @@ -388,10 +390,10 @@ namespace DualScreenDemo pictureBoxPinYinSongCoords.Height // 設定 高度 ); - // 將載入的圖片設定為 `pictureBoxPinYinSongs` 的影像 + // 將載入的圖片設定為 pictureBoxPinYinSongs 的影像 pictureBoxPinYinSongs.Image = originalImage; - // 調整 `PictureBox` 的大小與位置,使其符合 `displayArea` 的設定 + // 調整 PictureBox 的大小與位置,使其符合 displayArea 的設定 ResizeAndPositionPictureBox( pictureBoxPinYinSongs, displayArea.X, @@ -400,7 +402,7 @@ namespace DualScreenDemo displayArea.Height ); - // 顯示 `PictureBox` + // 顯示 PictureBox pictureBoxPinYinSongs.Visible = true; } @@ -416,7 +418,7 @@ namespace DualScreenDemo // 暫停佈局更新,以防止 UI 閃爍或重繪時出現異常 SuspendLayout(); - // 設定 `pictureBoxPinYinSongs` 的可見性 + // 設定 pictureBoxPinYinSongs 的可見性 pictureBoxPinYinSongs.Visible = isVisible; if (isVisible) pictureBoxPinYinSongs.BringToFront(); // 確保顯示時位於最前方 @@ -427,25 +429,25 @@ namespace DualScreenDemo if (isVisible) button.BringToFront(); } - // 設定 `modifyButtonPinYinSongs` (修改按鈕) 的可見性 + // 設定 modifyButtonPinYinSongs (修改按鈕) 的可見性 if (modifyButtonPinYinSongs != null) { modifyButtonPinYinSongs.Visible = isVisible; if (isVisible) modifyButtonPinYinSongs.BringToFront(); } - // 設定 `clearButtonPinYinSongs` (清除按鈕) 的可見性 + // 設定 clearButtonPinYinSongs (清除按鈕) 的可見性 if (clearButtonPinYinSongs != null) { clearButtonPinYinSongs.Visible = isVisible; if (isVisible) clearButtonPinYinSongs.BringToFront(); } - // 設定 `closeButtonPinYinSongs` (關閉按鈕) 的可見性 + // 設定 closeButtonPinYinSongs (關閉按鈕) 的可見性 closeButtonPinYinSongs.Visible = isVisible; if (isVisible) closeButtonPinYinSongs.BringToFront(); - // 設定 `inputBoxPinYinSongs` (輸入框) 的可見性 + // 設定 inputBoxPinYinSongs (輸入框) 的可見性 inputBoxPinYinSongs.Visible = isVisible; if (isVisible) inputBoxPinYinSongs.BringToFront(); @@ -453,7 +455,7 @@ namespace DualScreenDemo ResumeLayout(); PerformLayout(); - // 刷新 `pictureBoxPinYinSongs`,確保畫面更新 + // 刷新 pictureBoxPinYinSongs,確保畫面更新 pictureBoxPinYinSongs.Refresh(); // 刷新拼音字母按鈕