877 lines
40 KiB
C#
877 lines
40 KiB
C#
using System.IO;
|
||
using System.Drawing.Imaging;
|
||
using IniParser;
|
||
using IniParser.Model;
|
||
using System.Text;
|
||
|
||
/*
|
||
WordCountSongs -> SongIDSearch
|
||
WordCount -> SongID
|
||
numberWordCount -> numberSongID
|
||
NumberWordCount -> NumberSongID
|
||
inputBoxWordCountFontName -> inputBoxSongIDFontName
|
||
inputBoxWordCountFontSize -> inputBoxSongIDFontSize
|
||
inputBoxWordCountFontStyle -> inputBoxSongIDFontStyle
|
||
inputBoxWordCountForeColor -> inputBoxSongIDForeColor
|
||
LoadConfigDataforWordCountSongs -> LoadConfigDataforSongIDSearch
|
||
LoadButtonCoordinatesForWordCountSongs -> LoadButtonCoordinatesForSongIDSearch
|
||
LoadButtonImagesForWordCountSongs -> LoadButtonImagesForSongIDSearch
|
||
LoadSpecialButtonCoordinatesForWordCountSongs -> LoadSpecialButtonCoordinatesForSongIDSearch
|
||
RemoveWhiteBorderForWordCountSongs -> RemoveWhiteBorderForSongIDSearch
|
||
CreateSpecialButtonForWordCountSongs -> CreateSpecialButtonForSongIDSearch
|
||
LoadInputBoxConfigForWordCountSongs -> LoadInputBoxConfigForSongIDSearch
|
||
*/
|
||
|
||
|
||
namespace DualScreenDemo
|
||
{
|
||
public partial class PrimaryForm
|
||
{
|
||
private PictureBox pictureBoxSongIDSearch;
|
||
|
||
private Button[] numberSongIDButtonsForSongs;
|
||
private Button modifyButtonSongIDSearch;
|
||
private Button clearButtonSongIDSearch;
|
||
private Button closeButtonSongIDSearch;
|
||
|
||
private string[] numberSongIDSymbols;
|
||
private (int X, int Y, int Width, int Height)[] numberSongIDButtonCoords;
|
||
private Dictionary<string, (string normal, string mouseDown, string mouseOver)> numberSongIDButtonImages;
|
||
|
||
private (int X, int Y, int Width, int Height) modifyButtonSongIDCoords;
|
||
private (int X, int Y, int Width, int Height) clearButtonSongIDCoords;
|
||
private (int X, int Y, int Width, int Height) closeButtonSongIDCoords;
|
||
|
||
private RichTextBox inputBoxSongIDSearch;
|
||
|
||
private (int X, int Y, int Width, int Height) inputBoxSongIDCoords;
|
||
private string inputBoxSongIDFontName;
|
||
private float inputBoxSongIDFontSize;
|
||
private FontStyle inputBoxSongIDFontStyle;
|
||
private Color inputBoxSongIDForeColor;
|
||
|
||
/// <summary>
|
||
/// <para> 點擊「注音歌手搜尋」按鈕時執行的事件處理函式。</para>
|
||
/// <para>此函式負責更新按鈕的背景圖片、載入對應的歌手圖片,並切換相關 UI 控件的可見性。</para>
|
||
/// </summary>
|
||
/// <param name="sender">觸發事件的物件(通常是按鈕本身)。</param>
|
||
/// <param name="e">事件參數。</param>
|
||
private void SongIDSearchSongsButton_Click(object sender, EventArgs e)
|
||
{
|
||
// 設定按鈕背景,將「注音搜尋」設為啟動狀態,其餘按鈕恢復為正常狀態
|
||
zhuyinSearchSongButton.BackgroundImage = zhuyinSearchSongNormalBackground;
|
||
englishSearchSongButton.BackgroundImage = englishSearchSongNormalBackground;
|
||
pinyinSearchSongButton.BackgroundImage = pinyinSearchSongNormalBackground;
|
||
wordCountSearchSongButton.BackgroundImage = wordCountSearchSongNormalBackground;
|
||
handWritingSearchSongButton.BackgroundImage = handWritingSearchSongNormalBackground;
|
||
numberSearchSongButton.BackgroundImage = numberSearchSongActiveBackground;
|
||
|
||
|
||
|
||
// 載入設定檔,取得圖片路徑資訊
|
||
var configData = LoadConfigDataforSongIDSearch();
|
||
|
||
// 取得「注音歌手圖片」的完整路徑
|
||
string imagePath = Path.Combine(Application.StartupPath, configData["ImagePaths"]["SongIDSearch"]);
|
||
|
||
// 在 PictureBox 中顯示對應的「注音歌手」圖片
|
||
ShowImageOnPictureBoxSongIDSearch(Path.Combine(Application.StartupPath, imagePath));
|
||
|
||
// 鍵盤UI介面顯示設定
|
||
SetWordCountSongsAndButtonsVisibility(false);
|
||
SetEnglishSongsAndButtonsVisibility(false);
|
||
SetPinYinSongsAndButtonsVisibility(false);
|
||
SetHandWritingForSongsAndButtonsVisibility(false);
|
||
SetSongIDSearchAndButtonsVisibility(true);
|
||
SetZhuYinSongsAndButtonsVisibility(false);
|
||
|
||
ResetinputBox();
|
||
SetSongIDSearchAndButtonsVisibility(true); // 顯示字數搜尋相關控件
|
||
// 顯示「注音歌手搜尋」的圖片框
|
||
pictureBoxSongIDSearch.Visible = true;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// <para>從 config.ini 設定檔中載入注音符號(NumberWordCount Symbols)。</para>
|
||
/// <para>讀取 ini 檔的 [NumberWordCountSymbols] 區塊,並將「Symbols」欄位的值解析為陣列。</para>
|
||
/// </summary>
|
||
private void LoadNumberSongIDSymbolsFromConfig()
|
||
{
|
||
// 建立 INI 檔案解析器
|
||
var parser = new FileIniDataParser();
|
||
|
||
// 設定檔路徑
|
||
string iniFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config.ini");
|
||
|
||
|
||
IniData data;
|
||
|
||
// 以 UTF-8 編碼開啟並讀取 INI 檔案
|
||
using (var reader = new StreamReader(iniFilePath, Encoding.UTF8))
|
||
{
|
||
// 解析 INI 檔內容
|
||
data = parser.ReadData(reader);
|
||
}
|
||
|
||
// 取得 [NumberSongIDSymbols] 區塊中的 "Symbols" 欄位內容
|
||
string symbols = data["NumberSongIDSymbols"]["Symbols"];
|
||
|
||
// 將符號字串以逗號分隔,轉換為字串陣列
|
||
numberSongIDSymbols = symbols.Split(',');
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 從設定檔 (config.ini) 載入 INI 設定數據。
|
||
/// </summary>
|
||
/// <returns>回傳解析後的 INI 設定數據 (IniData)。</returns>
|
||
private IniData LoadConfigDataforSongIDSearch()
|
||
{
|
||
var parser = new FileIniDataParser();
|
||
string iniFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config.ini");
|
||
|
||
|
||
// 使用 UTF-8 讀取 INI 檔案並解析內容
|
||
using (var reader = new StreamReader(iniFilePath, Encoding.UTF8))
|
||
{
|
||
return parser.ReadData(reader);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 從 INI 設定數據中讀取注音符號 (NumberSongID Symbols)。
|
||
/// </summary>
|
||
/// <param name="data">已解析的 INI 設定數據。</param>
|
||
/// <returns>回傳包含注音符號的字串陣列。</returns>
|
||
private string[] LoadNumberSongIDSymbols(IniData data)
|
||
{
|
||
// 從 INI 檔案的 [NumberSongIDSymbols] 區塊取得 Symbols 欄位值
|
||
string symbols = data["NumberSongIDSymbols"]["Symbols"];
|
||
|
||
// 以逗號分隔字串並轉換為字串陣列
|
||
return symbols.Split(',');
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 從 INI 設定數據中載入按鈕座標資料。
|
||
/// </summary>
|
||
/// <param name="data">已解析的 INI 設定數據。</param>
|
||
/// <param name="section">設定檔中按鈕座標所屬的區塊名稱。</param>
|
||
/// <param name="buttonCount">按鈕數量。</param>
|
||
/// <returns>回傳包含按鈕座標的陣列,每個元素是由 (X, Y, Width, Height) 組成的元組。</returns>
|
||
private (int X, int Y, int Width, int Height)[] LoadButtonCoordinatesForSongIDSearch(IniData data, string section, int buttonCount)
|
||
{
|
||
var buttonList = new List<(int X, int Y, int Width, int Height)>();
|
||
|
||
// 迴圈讀取每個按鈕的座標設定
|
||
for (int i = 1; i <= buttonCount; i++)
|
||
{
|
||
// 取得按鈕座標的字串 (格式: X,Y,Width,Height)
|
||
var coordString = data[section][$"button{i}"];
|
||
var coords = coordString.Split(',');
|
||
|
||
// 將座標資料轉換為 (X, Y, Width, Height) 元組並加入清單
|
||
buttonList.Add((
|
||
int.Parse(coords[0]), // X 座標
|
||
int.Parse(coords[1]), // Y 座標
|
||
int.Parse(coords[2]), // 寬度
|
||
int.Parse(coords[3]) // 高度
|
||
));
|
||
}
|
||
|
||
// 回傳所有按鈕座標的陣列
|
||
return buttonList.ToArray();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 從 INI 設定數據中載入按鈕圖片檔案路徑資料 (包含正常、點擊、滑鼠移過圖片)。
|
||
/// </summary>
|
||
/// <param name="data">已解析的 INI 設定數據。</param>
|
||
/// <param name="section">設定檔中按鈕圖片設定所屬的區塊名稱。</param>
|
||
/// <param name="buttonCount">按鈕數量。</param>
|
||
/// <returns>回傳一個字典,鍵是按鈕名稱,值是包含正常、點擊和滑鼠移過狀態的元組。</returns>
|
||
private Dictionary<string, (string normal, string mouseDown, string mouseOver)> LoadButtonImagesForSongIDSearch(IniData data, string section, int buttonCount)
|
||
{
|
||
var buttonImages = new Dictionary<string, (string normal, string mouseDown, string mouseOver)>();
|
||
|
||
// 迴圈讀取每個按鈕的圖片設定
|
||
for (int i = 0; i < 10; i++)
|
||
{
|
||
// 讀取按鈕的三種圖片狀態:正常、點擊、滑鼠移過
|
||
buttonImages[$"button{i}"] = (
|
||
data[section][$"button{i}_normal"], // 正常狀態圖片路徑
|
||
data[section][$"button{i}_mouseDown"], // 點擊狀態圖片路徑
|
||
data[section][$"button{i}_mouseOver"] // 滑鼠移過狀態圖片路徑
|
||
);
|
||
}
|
||
|
||
// 回傳包含所有按鈕圖片路徑資料的字典
|
||
return buttonImages;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 從 INI 設定數據中載入特定按鈕的座標資料。
|
||
/// </summary>
|
||
/// <param name="data">已解析的 INI 設定數據。</param>
|
||
/// <param name="section">設定檔中按鈕座標所屬的區塊名稱。</param>
|
||
/// <param name="buttonKey">指定按鈕的鍵名 (如 "button1")。</param>
|
||
/// <returns>回傳包含按鈕座標的元組 (X, Y, Width, Height)。</returns>
|
||
private (int X, int Y, int Width, int Height) LoadSpecialButtonCoordinatesForSongIDSearch(IniData data, string section, string buttonKey)
|
||
{
|
||
// 取得按鈕座標的字串 (格式: X,Y,Width,Height)
|
||
var coords = data[section][buttonKey].Split(',');
|
||
|
||
// 解析座標字串並回傳 (X, Y, Width, Height) 元組
|
||
return (int.Parse(coords[0]), int.Parse(coords[1]), int.Parse(coords[2]), int.Parse(coords[3]));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 從 INI 設定數據中載入按鈕的圖片資料 (包含正常、點擊、滑鼠移過圖片)。
|
||
/// </summary>
|
||
/// <param name="data">已解析的 INI 設定數據。</param>
|
||
/// <param name="section">設定檔中按鈕圖片設定所屬的區塊名稱。</param>
|
||
/// <returns>回傳包含按鈕三種狀態圖片路徑的元組 (normal, mouseDown, mouseOver)。</returns>
|
||
private (string normal, string mouseDown, string mouseOver) LoadButtonImagesForSongIDSearch(IniData data, string section)
|
||
{
|
||
// 讀取按鈕三種狀態的圖片路徑
|
||
return (
|
||
data[section]["normal"], // 正常狀態圖片路徑
|
||
data[section]["mouseDown"], // 點擊狀態圖片路徑
|
||
data[section]["mouseOver"] // 滑鼠移過狀態圖片路徑
|
||
);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 初始化並設置語音按鈕的相關資料,包括符號、座標與圖片等。
|
||
/// </summary>
|
||
private void InitializeNumberSongIDButtons()
|
||
{
|
||
// 載入配置資料
|
||
var data = LoadConfigDataforSongIDSearch();
|
||
|
||
// 載入語音符號(如拼音、注音符號等)
|
||
numberSongIDSymbols = LoadNumberSongIDSymbols(data);
|
||
|
||
// 載入按鈕座標資料
|
||
numberSongIDButtonCoords = LoadButtonCoordinatesForSongIDSearch(data, "NumberSongIDButtonCoordinates", 10);
|
||
|
||
// 載入按鈕圖片資料
|
||
numberSongIDButtonImages = LoadButtonImagesForSongIDSearch(data, "NumberSongIDButtonImages", 10);
|
||
|
||
// 初始化語音按鈕陣列,總共有 10 個按鈕
|
||
numberSongIDButtonsForSongs = new Button[10];
|
||
|
||
// 設置每個語音按鈕
|
||
for (int i = 0; i < 10; i++)
|
||
{
|
||
// 根據按鈕索引讀取其圖片資料
|
||
var buttonImages = numberSongIDButtonImages[$"button{i}"];
|
||
|
||
// 創建並初始化語音按鈕,設定其背景圖片
|
||
CreateNumberSongIDButton(i, buttonImages.normal, buttonImages.mouseDown, buttonImages.mouseOver);
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 創建一個語音按鈕,並為其設置圖片、座標、事件等屬性。
|
||
/// </summary>
|
||
/// <param name="index">按鈕的索引,用來獲取對應的語音符號、座標和圖片資料。</param>
|
||
/// <param name="normalImagePath">正常狀態下的圖片路徑。</param>
|
||
/// <param name="mouseDownImagePath">點擊狀態下的圖片路徑。</param>
|
||
/// <param name="mouseOverImagePath">滑鼠移過狀態下的圖片路徑。</param>
|
||
private void CreateNumberSongIDButton(int index, string normalImagePath, string mouseDownImagePath, string mouseOverImagePath)
|
||
{
|
||
try
|
||
{
|
||
// 創建語音按鈕並設置其屬性
|
||
numberSongIDButtonsForSongs[index] = new Button
|
||
{
|
||
Name = $"numberSongIDButton_{numberSongIDSymbols[index]}", // 按鈕名稱設為語音符號名稱
|
||
BackgroundImage = Image.FromFile(Path.Combine(Application.StartupPath, normalImagePath)), // 設定背景圖片
|
||
BackgroundImageLayout = ImageLayout.Stretch, // 設定圖片拉伸樣式
|
||
FlatStyle = FlatStyle.Flat, // 設定為平面風格
|
||
FlatAppearance = { BorderSize = 0 } // 設定無邊框
|
||
};
|
||
|
||
// 調整按鈕大小並設置位置
|
||
ResizeAndPositionButton(numberSongIDButtonsForSongs[index], numberSongIDButtonCoords[index].X, numberSongIDButtonCoords[index].Y,
|
||
numberSongIDButtonCoords[index].Width, numberSongIDButtonCoords[index].Height);
|
||
|
||
// 從檔案中讀取正常、點擊和滑鼠懸停狀態的圖片
|
||
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));
|
||
|
||
// 設置滑鼠事件:點擊、進入、離開等,改變按鈕的背景圖片
|
||
numberSongIDButtonsForSongs[index].MouseDown += (s, e) => numberSongIDButtonsForSongs[index].BackgroundImage = mouseDownImage;
|
||
numberSongIDButtonsForSongs[index].MouseUp += (s, e) => numberSongIDButtonsForSongs[index].BackgroundImage = normalImage;
|
||
numberSongIDButtonsForSongs[index].MouseEnter += (s, e) => numberSongIDButtonsForSongs[index].BackgroundImage = mouseOverImage;
|
||
numberSongIDButtonsForSongs[index].MouseLeave += (s, e) => numberSongIDButtonsForSongs[index].BackgroundImage = normalImage;
|
||
|
||
// 設置點擊事件處理方法
|
||
numberSongIDButtonsForSongs[index].Click += NumberSongIDButton_Click;
|
||
|
||
// 設置按鈕的 Tag 屬性為對應的語音符號
|
||
numberSongIDButtonsForSongs[index].Tag = numberSongIDSymbols[index];
|
||
|
||
// 將按鈕添加到表單的控制項集合中
|
||
this.Controls.Add(numberSongIDButtonsForSongs[index]);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
// 捕捉錯誤並輸出錯誤訊息
|
||
Console.WriteLine($"Error creating button at index {index}: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 初始化所有與注音歌手相關的按鈕,包括語音符號按鈕、特殊按鈕及輸入框。
|
||
/// </summary>
|
||
private void InitializeButtonsForSongIDSearch()
|
||
{
|
||
// 從配置檔案加載注音符號並初始化按鈕
|
||
LoadNumberSongIDSymbolsFromConfig();
|
||
|
||
// 初始化所有語音按鈕
|
||
InitializeNumberSongIDButtons();
|
||
|
||
// 初始化注音歌手的特殊按鈕(例如音量、搜尋等)
|
||
InitializeSpecialButtonsForSongIDSearch();
|
||
|
||
// 初始化注音歌手的輸入框
|
||
InitializeInputBoxSongIDSearch();
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 移除圖像周圍的白色邊框,將邊框的像素透明化。
|
||
/// </summary>
|
||
/// <param name="imagePath">待處理的圖像文件路徑。</param>
|
||
/// <returns>處理後的圖像,其中白色邊框已被去除並替換為透明。</returns>
|
||
private Image RemoveWhiteBorderForSongIDSearch(string imagePath)
|
||
{
|
||
// 創建一個 Bitmap 物件來加載圖像
|
||
Bitmap bmp = new Bitmap(imagePath);
|
||
|
||
// 定義圖像的矩形區域,這是我們將要操作的區域
|
||
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
|
||
|
||
// 鎖定圖像的位圖數據,以便進行直接修改
|
||
BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);
|
||
|
||
IntPtr ptr = bmpData.Scan0; // 獲取位圖數據的起始位置
|
||
int bytes = Math.Abs(bmpData.Stride) * bmp.Height; // 計算圖像的總字節數
|
||
byte[] rgbValues = new byte[bytes]; // 用來存儲圖像的像素數據
|
||
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes); // 從圖像數據中複製像素數據到 rgbValues 陣列
|
||
|
||
// 遍歷每個像素點,檢查是否為白色邊框
|
||
for (int y = 0; y < bmp.Height; y++)
|
||
{
|
||
for (int x = 0; x < bmp.Width; x++)
|
||
{
|
||
int position = (y * bmpData.Stride) + (x * 4); // 計算當前像素的位址
|
||
byte b = rgbValues[position]; // 藍色分量
|
||
byte g = rgbValues[position + 1]; // 綠色分量
|
||
byte r = rgbValues[position + 2]; // 紅色分量
|
||
byte a = rgbValues[position + 3]; // alpha 分量(透明度)
|
||
|
||
// 如果當前像素在圖像邊緣且為白色 (255, 255, 255),則將其設為透明
|
||
if ((x < 5 || x > bmp.Width - 5 || y < 5 || y > bmp.Height - 5) && r == 255 && g == 255 && b == 255)
|
||
{
|
||
// 將白色像素的 RGB 設置為 255, 255, 255 且 alpha 設為 0 (透明)
|
||
rgbValues[position] = 255;
|
||
rgbValues[position + 1] = 255;
|
||
rgbValues[position + 2] = 255;
|
||
rgbValues[position + 3] = 0; // 透明
|
||
}
|
||
}
|
||
}
|
||
|
||
// 將修改後的像素數據重新複製回位圖數據
|
||
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
|
||
|
||
// 解鎖圖像數據
|
||
bmp.UnlockBits(bmpData);
|
||
|
||
// 返回處理後的圖像
|
||
return bmp;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 初始化與注音歌手相關的特殊按鈕,包括修改、清除和關閉按鈕。
|
||
/// </summary>
|
||
private void InitializeSpecialButtonsForSongIDSearch()
|
||
{
|
||
// 初始化修改按鈕
|
||
InitializeModifyButtonSongIDSearch();
|
||
|
||
// 初始化清除按鈕
|
||
InitializeClearButtonSongIDSearch();
|
||
|
||
// 初始化關閉按鈕
|
||
InitializeCloseButtonSongIDSearch();
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 初始化「修改」按鈕,設定按鈕的坐標、圖片和點擊事件。
|
||
/// </summary>
|
||
private void InitializeModifyButtonSongIDSearch()
|
||
{
|
||
// 加載配置數據
|
||
var data = LoadConfigDataforSongIDSearch();
|
||
|
||
// 讀取按鈕坐標
|
||
modifyButtonSongIDCoords = LoadSpecialButtonCoordinatesForSongIDSearch(data, "SpecialButtonCoordinates", "modifyButtonSongIDSearch");
|
||
|
||
// 加載按鈕圖片(正常、鼠標懸停、鼠標按下)
|
||
var buttonImages = LoadButtonImagesForSongIDSearch(data, "ModifyButtonImagesSongID");
|
||
|
||
// 創建「修改」按鈕,並設置坐標、圖片及點擊事件
|
||
modifyButtonSongIDSearch = CreateSpecialButtonForSongIDSearch(
|
||
"btnModifySongIDSearch", // 按鈕名稱
|
||
modifyButtonSongIDCoords, // 按鈕坐標
|
||
buttonImages.normal, // 正常狀態圖片
|
||
buttonImages.mouseOver, // 鼠標懸停圖片
|
||
buttonImages.mouseDown, // 鼠標按下圖片
|
||
ModifyButtonSongIDSearch_Click // 按鈕點擊事件
|
||
);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 處理「修改」按鈕的點擊事件,該事件會刪除輸入框中的最後一個字符。
|
||
/// </summary>
|
||
/// <param name="sender">觸發事件的對象</param>
|
||
/// <param name="e">事件參數</param>
|
||
private void ModifyButtonSongIDSearch_Click(object sender, EventArgs e)
|
||
{
|
||
// 如果輸入框不為空,且包含輸入內容,則刪除最後一個字符
|
||
if (this.Controls.Contains(inputBoxSongIDSearch) && inputBoxSongIDSearch.Text.Length > 0)
|
||
{
|
||
inputBoxSongIDSearch.Text = inputBoxSongIDSearch.Text.Substring(0, inputBoxSongIDSearch.Text.Length - 1);
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 初始化「清除」按鈕,設定按鈕的坐標、圖片和點擊事件。
|
||
/// </summary>
|
||
private void InitializeClearButtonSongIDSearch()
|
||
{
|
||
// 加載配置數據
|
||
var data = LoadConfigDataforSongIDSearch();
|
||
|
||
// 讀取按鈕坐標
|
||
clearButtonSongIDCoords = LoadSpecialButtonCoordinatesForSongIDSearch(data, "SpecialButtonCoordinates", "clearButtonSongIDSearch");
|
||
|
||
// 加載按鈕圖片(正常、鼠標懸停、鼠標按下)
|
||
var buttonImages = LoadButtonImagesForSongIDSearch(data, "ClearButtonImagesSongID");
|
||
|
||
// 創建「清除」按鈕,並設置坐標、圖片及點擊事件
|
||
clearButtonSongIDSearch = CreateSpecialButtonForSongIDSearch(
|
||
"btnClearSongIDSearch", // 按鈕名稱
|
||
clearButtonSongIDCoords, // 按鈕坐標
|
||
buttonImages.normal, // 正常狀態圖片
|
||
buttonImages.mouseOver, // 鼠標懸停圖片
|
||
buttonImages.mouseDown, // 鼠標按下圖片
|
||
ClearButtonSongIDSearch_Click // 按鈕點擊事件
|
||
);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 處理「清除」按鈕的點擊事件,該事件會清空輸入框中的所有文本。
|
||
/// </summary>
|
||
/// <param name="sender">觸發事件的對象</param>
|
||
/// <param name="e">事件參數</param>
|
||
private void ClearButtonSongIDSearch_Click(object sender, EventArgs e)
|
||
{
|
||
// 如果輸入框不為空,則清空該框的文本內容
|
||
if (this.Controls.Contains(inputBoxSongIDSearch) && inputBoxSongIDSearch.Text.Length > 0)
|
||
{
|
||
inputBoxSongIDSearch.Text = "";
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 初始化「關閉」按鈕,設定按鈕的坐標、圖片和點擊事件。
|
||
/// </summary>
|
||
private void InitializeCloseButtonSongIDSearch()
|
||
{
|
||
// 加載配置數據
|
||
var data = LoadConfigDataforSongIDSearch();
|
||
|
||
// 讀取按鈕坐標
|
||
closeButtonSongIDCoords = LoadSpecialButtonCoordinatesForSongIDSearch(data, "SpecialButtonCoordinates", "closeButtonSongIDSearch");
|
||
|
||
// 加載按鈕圖片(正常、鼠標懸停、鼠標按下)
|
||
var buttonImages = LoadButtonImagesForSongIDSearch(data, "CloseButtonImagesSongID");
|
||
|
||
// 創建「關閉」按鈕,並設置坐標、圖片及點擊事件
|
||
closeButtonSongIDSearch = CreateSpecialButtonForSongIDSearch(
|
||
"btnCloseSongIDSearch", // 按鈕名稱
|
||
closeButtonSongIDCoords, // 按鈕坐標
|
||
buttonImages.normal, // 正常狀態圖片
|
||
buttonImages.mouseOver, // 鼠標懸停圖片
|
||
buttonImages.mouseDown, // 鼠標按下圖片
|
||
CloseButtonSongIDSearch_Click // 按鈕點擊事件
|
||
);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 「關閉」按鈕的點擊事件處理方法。
|
||
/// 隱藏 SongID 歌手圖片框以及與其相關的按鈕。
|
||
/// </summary>
|
||
/// <param name="sender">觸發事件的對象,這裡是關閉按鈕。</param>
|
||
/// <param name="e">事件參數。</param>
|
||
private void CloseButtonSongIDSearch_Click(object sender, EventArgs e)
|
||
{
|
||
// 隱藏 SongID 歌手圖片框
|
||
pictureBoxSongIDSearch.Visible = false;
|
||
|
||
numberSearchSongButton.BackgroundImage = numberSearchSongNormalBackground;
|
||
// 隱藏與 SongID 歌手相關的所有按鈕
|
||
SetSongIDSearchAndButtonsVisibility(false);
|
||
FindNumberSongs(); // 搜尋歌曲
|
||
}
|
||
|
||
private void FindNumberSongs(){
|
||
string searchText = inputBoxSongIDSearch.Text;
|
||
// 在這裡添加搜尋歌曲的邏輯
|
||
// 例如:根據輸入框的內容搜尋歌曲
|
||
if (string.IsNullOrEmpty(searchText))
|
||
{
|
||
// 如果輸入框為空,則不進行搜尋
|
||
return;
|
||
}
|
||
string query = $"SELECT * FROM song_library_cache WHERE `song_id` = '{searchText}';";
|
||
|
||
var searchResults = SearchSongs_Mysql(query);
|
||
// 重置分頁
|
||
currentPage = 0;
|
||
currentSongList = searchResults;
|
||
totalPages = (int)Math.Ceiling((double)searchResults.Count / itemsPerPage);
|
||
// 更新多頁面面板的內容
|
||
multiPagePanel.currentPageIndex = 0;
|
||
multiPagePanel.LoadSongs(currentSongList);
|
||
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 創建一個特殊的按鈕,並設定其顯示屬性、事件處理和位置。
|
||
/// </summary>
|
||
/// <param name="name">按鈕的名稱。</param>
|
||
/// <param name="coords">按鈕的坐標和大小,包含 X, Y, 寬度和高度。</param>
|
||
/// <param name="normalImagePath">按鈕正常狀態下的背景圖片路徑。</param>
|
||
/// <param name="mouseOverImagePath">鼠標懸停時按鈕的背景圖片路徑。</param>
|
||
/// <param name="mouseDownImagePath">鼠標點擊時按鈕的背景圖片路徑。</param>
|
||
/// <param name="clickEventHandler">按鈕的點擊事件處理程序。</param>
|
||
/// <returns>創建並返回的按鈕對象。</returns>
|
||
private Button CreateSpecialButtonForSongIDSearch(string name, (int X, int Y, int Width, int Height) coords, string normalImagePath, string mouseOverImagePath, string mouseDownImagePath, EventHandler clickEventHandler)
|
||
{
|
||
// 創建按鈕並設定基本屬性
|
||
var button = new Button
|
||
{
|
||
Name = name,
|
||
FlatStyle = FlatStyle.Flat,
|
||
FlatAppearance = { BorderSize = 0, MouseDownBackColor = Color.Transparent, MouseOverBackColor = Color.Transparent },
|
||
BackgroundImageLayout = ImageLayout.Stretch,
|
||
BackgroundImage = Image.FromFile(Path.Combine(Application.StartupPath, normalImagePath))
|
||
};
|
||
|
||
// 設定按鈕的大小和位置
|
||
ResizeAndPositionButton(button, coords.X, coords.Y, coords.Width, coords.Height);
|
||
|
||
// 設定鼠標事件:進入、離開、按下、放開
|
||
button.MouseEnter += (sender, e) => button.BackgroundImage = Image.FromFile(Path.Combine(Application.StartupPath, mouseOverImagePath));
|
||
button.MouseLeave += (sender, e) => button.BackgroundImage = Image.FromFile(Path.Combine(Application.StartupPath, normalImagePath));
|
||
button.MouseDown += (sender, e) => button.BackgroundImage = Image.FromFile(Path.Combine(Application.StartupPath, mouseDownImagePath));
|
||
button.MouseUp += (sender, e) => button.BackgroundImage = Image.FromFile(Path.Combine(Application.StartupPath, normalImagePath));
|
||
|
||
// 註冊點擊事件處理
|
||
button.Click += clickEventHandler;
|
||
|
||
// 將按鈕添加到控件集合中
|
||
this.Controls.Add(button);
|
||
|
||
return button;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 初始化 SongID 歌手的輸入框,並設定其屬性與事件處理程序。
|
||
/// </summary>
|
||
private void InitializeInputBoxSongIDSearch()
|
||
{
|
||
try
|
||
{
|
||
// 加載輸入框配置
|
||
LoadInputBoxConfigForSongIDSearch();
|
||
|
||
// 創建一個 RichTextBox 控件來作為輸入框
|
||
inputBoxSongIDSearch = new RichTextBox
|
||
{
|
||
Name = "inputBoxSongIDSearch",
|
||
ForeColor = inputBoxSongIDForeColor, // 設定文字顏色
|
||
Font = new Font(inputBoxSongIDFontName, inputBoxSongIDFontSize, inputBoxSongIDFontStyle), // 設定字體樣式
|
||
ScrollBars = RichTextBoxScrollBars.None // 不顯示滾動條
|
||
};
|
||
|
||
// 調整和定位輸入框的位置及大小
|
||
ResizeAndPositionControl(inputBoxSongIDSearch, inputBoxSongIDCoords.X, inputBoxSongIDCoords.Y, inputBoxSongIDCoords.Width, inputBoxSongIDCoords.Height);
|
||
|
||
// 將輸入框加入到窗體的控件集合中
|
||
this.Controls.Add(inputBoxSongIDSearch);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
// 如果初始化過程中出現錯誤,則在控制台輸出錯誤信息
|
||
Console.WriteLine("Error initializing inputBoxSongIDSearch: " + ex.Message);
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 從配置文件 `config.ini` 中加載輸入框的設置,包括位置、大小、字體等屬性。
|
||
/// </summary>
|
||
private void LoadInputBoxConfigForSongIDSearch()
|
||
{
|
||
try
|
||
{
|
||
// 創建 INI 解析器
|
||
var parser = new FileIniDataParser();
|
||
string iniFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config.ini");
|
||
|
||
|
||
IniData data;
|
||
// 打開並讀取配置文件
|
||
using (var reader = new StreamReader(iniFilePath, Encoding.UTF8))
|
||
{
|
||
data = parser.ReadData(reader);
|
||
}
|
||
|
||
// 從配置中加載輸入框的坐標和大小
|
||
inputBoxSongIDCoords = (
|
||
int.Parse(data["InputBoxSongIDSearch"]["X"]), // 輸入框的 X 坐標
|
||
int.Parse(data["InputBoxSongIDSearch"]["Y"]), // 輸入框的 Y 坐標
|
||
int.Parse(data["InputBoxSongIDSearch"]["Width"]), // 輸入框的寬度
|
||
int.Parse(data["InputBoxSongIDSearch"]["Height"]) // 輸入框的高度
|
||
);
|
||
|
||
// 從配置中加載字體屬性
|
||
inputBoxSongIDFontName = data["InputBoxSongIDSearch"]["FontName"]; // 字體名稱
|
||
inputBoxSongIDFontSize = float.Parse(data["InputBoxSongIDSearch"]["FontSize"]); // 字體大小
|
||
inputBoxSongIDFontStyle = (FontStyle)Enum.Parse(typeof(FontStyle), data["InputBoxSongIDSearch"]["FontStyle"]); // 字體樣式
|
||
inputBoxSongIDForeColor = Color.FromName(data["InputBoxSongIDSearch"]["ForeColor"]); // 字體顏色
|
||
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
// 若發生錯誤,顯示錯誤信息
|
||
Console.WriteLine("Error loading inputBox configuration: " + ex.Message);
|
||
}
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 存儲 `pictureBoxSongIDSearch` 控制項的坐標和大小設置。
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// 這個元組包含了 `X`、`Y` 坐標以及 `Width`、`Height` 大小,用於配置 `pictureBoxSongIDSearch` 的位置和大小。
|
||
/// </remarks>
|
||
private (int X, int Y, int Width, int Height) pictureBoxSongIDSongCoords;
|
||
|
||
/// <summary>
|
||
/// 從配置檔案中讀取 `PictureBoxSongIDSearch` 控制項的坐標和大小設置。
|
||
/// </summary>
|
||
private void LoadPictureBoxSongIDSongCoordsFromConfig()
|
||
{
|
||
var parser = new FileIniDataParser();
|
||
string iniPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config.ini");
|
||
IniData data = parser.ReadFile(iniPath);
|
||
|
||
|
||
var coords = data["PictureBoxSongIDSearch"];
|
||
pictureBoxSongIDSongCoords = (
|
||
int.Parse(coords["X"]),
|
||
int.Parse(coords["Y"]),
|
||
int.Parse(coords["Width"]),
|
||
int.Parse(coords["Height"])
|
||
);
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 顯示圖片並根據配置文件設置顯示區域的大小和位置。
|
||
/// </summary>
|
||
/// <param name="imagePath">圖片的路徑。</param>
|
||
private void ShowImageOnPictureBoxSongIDSearch(string imagePath)
|
||
{
|
||
// 讀取配置文件中的顯示區域設置
|
||
LoadPictureBoxSongIDSongCoordsFromConfig();
|
||
|
||
// 加載原始圖片
|
||
Bitmap originalImage = new Bitmap(imagePath);
|
||
|
||
// 創建顯示區域,根據配置文件中的坐標和大小設置
|
||
Rectangle displayArea = new Rectangle(pictureBoxSongIDSongCoords.X, pictureBoxSongIDSongCoords.Y, pictureBoxSongIDSongCoords.Width, pictureBoxSongIDSongCoords.Height);
|
||
|
||
// 設置圖片到 PictureBox
|
||
pictureBoxSongIDSearch.Image = originalImage;
|
||
|
||
// 調整 PictureBox 大小和位置
|
||
ResizeAndPositionPictureBox(pictureBoxSongIDSearch, displayArea.X, displayArea.Y, displayArea.Width, displayArea.Height);
|
||
|
||
// 顯示圖片
|
||
pictureBoxSongIDSearch.Visible = true;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 設置注音歌手相關控制項(包括圖片框、按鈕和輸入框)的顯示或隱藏狀態。
|
||
/// </summary>
|
||
/// <param name="isVisible">指定控件是否可見。True 為顯示,False 為隱藏。</param>
|
||
private void SetSongIDSearchAndButtonsVisibility(bool isVisible)
|
||
{
|
||
// 定義一個動作來處理控制項的顯示或隱藏
|
||
System.Action action = () =>
|
||
{
|
||
try
|
||
{
|
||
// 暫停控制項佈局的重新排版,提高效率
|
||
SuspendLayout();
|
||
|
||
// 檢查並設置圖片框的可見性
|
||
if (pictureBoxSongIDSearch == null)
|
||
{
|
||
Console.WriteLine("pictureBoxSongIDSearch is null");
|
||
}
|
||
else
|
||
{
|
||
pictureBoxSongIDSearch.Visible = isVisible;
|
||
if (isVisible) pictureBoxSongIDSearch.BringToFront(); // 如果顯示,將其置於最前
|
||
}
|
||
|
||
// 檢查並設置拼音按鈕的可見性
|
||
if (numberSongIDButtonsForSongs == null)
|
||
{
|
||
Console.WriteLine("numberSongIDButtonsForSongs is null");
|
||
}
|
||
else
|
||
{
|
||
foreach (var button in numberSongIDButtonsForSongs)
|
||
{
|
||
if (button == null)
|
||
{
|
||
Console.WriteLine("One of the numberSongIDButtonsForSongs is null");
|
||
}
|
||
else
|
||
{
|
||
button.Visible = isVisible;
|
||
if (isVisible) button.BringToFront(); // 如果顯示,將其置於最前
|
||
}
|
||
}
|
||
}
|
||
|
||
// 檢查並設置修改按鈕的可見性
|
||
if (modifyButtonSongIDSearch == null)
|
||
{
|
||
Console.WriteLine("modifyButtonSongIDSearch is null");
|
||
}
|
||
else
|
||
{
|
||
modifyButtonSongIDSearch.Visible = isVisible;
|
||
if (isVisible) modifyButtonSongIDSearch.BringToFront(); // 如果顯示,將其置於最前
|
||
}
|
||
|
||
// 檢查並設置清除按鈕的可見性
|
||
if (clearButtonSongIDSearch == null)
|
||
{
|
||
Console.WriteLine("clearButtonSongIDSearch is null");
|
||
}
|
||
else
|
||
{
|
||
clearButtonSongIDSearch.Visible = isVisible;
|
||
if (isVisible) clearButtonSongIDSearch.BringToFront(); // 如果顯示,將其置於最前
|
||
}
|
||
|
||
// 檢查並設置關閉按鈕的可見性
|
||
if (closeButtonSongIDSearch == null)
|
||
{
|
||
Console.WriteLine("closeButtonSongIDSearch is null");
|
||
}
|
||
else
|
||
{
|
||
closeButtonSongIDSearch.Visible = isVisible;
|
||
if (isVisible) closeButtonSongIDSearch.BringToFront(); // 如果顯示,將其置於最前
|
||
}
|
||
|
||
// 檢查並設置輸入框的可見性
|
||
if (inputBoxSongIDSearch == null)
|
||
{
|
||
Console.WriteLine("inputBoxSongIDSearch is null");
|
||
}
|
||
else
|
||
{
|
||
inputBoxSongIDSearch.Visible = isVisible;
|
||
if (isVisible) inputBoxSongIDSearch.BringToFront(); // 如果顯示,將其置於最前
|
||
}
|
||
|
||
// 恢復控制項的佈局重新排版
|
||
ResumeLayout();
|
||
PerformLayout();
|
||
|
||
// 刷新所有控制項的顯示
|
||
pictureBoxSongIDSearch?.Refresh();
|
||
if (numberSongIDButtonsForSongs != null)
|
||
{
|
||
foreach (var button in numberSongIDButtonsForSongs)
|
||
{
|
||
button?.Refresh(); // 刷新每個按鈕
|
||
}
|
||
}
|
||
modifyButtonSongIDSearch?.Refresh();
|
||
clearButtonSongIDSearch?.Refresh();
|
||
closeButtonSongIDSearch?.Refresh();
|
||
inputBoxSongIDSearch?.Refresh();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine("Error in SetSongIDSearchAndButtonsVisibility: " + ex.Message);
|
||
}
|
||
};
|
||
|
||
// 檢查是否需要在主執行緒外執行
|
||
if (this.InvokeRequired)
|
||
{
|
||
this.Invoke(action); // 如果需要,透過主執行緒執行
|
||
}
|
||
else
|
||
{
|
||
action(); // 否則直接執行
|
||
}
|
||
}
|
||
private void NumberSongIDButton_Click(object sender, EventArgs e)
|
||
{
|
||
var button = sender as Button;
|
||
if (button != null && button.Tag != null)
|
||
{
|
||
|
||
if (inputBoxSongIDSearch.Visible)
|
||
{
|
||
inputBoxSongIDSearch.Text += button.Tag.ToString();
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
} |