--- tags: 視窗程式設計 --- # 實作:記事本(字型、字體大小、樣式) 之前我們完成的記事本,已經具有基本純文字編輯的功能,不過我們如果希望文字的樣式要修改,就沒有辦法了,現在我們要介紹如何實現基本的文字樣式編輯功能。 # 第一部分:介面設定 大多數可以編輯文字樣式的文字編輯器,都會有一個類似下拉選單的按鍵可以按,按下去之後就會有選項選擇。 這樣的控制項叫做「**下拉選單(ComboBox)**」,這個控制項和清單方塊有點類似,一樣可以顯示一連串的資料,但差異點就是要按下去才會顯示清單,這樣可以讓視窗介面更加簡潔。 我們要設計的樣子就像這樣,你可以看到下圖有三個下拉選單,分別可以設定字型、字體大小、樣式。 ![](https://imgur.com/LGEKvBK.png) 同樣的和大多數控制項類似,在工具箱裡面你可以找到下拉選單,也是一樣可以直接置放到視窗畫面之上,你可以再調整成你要的大小。 ![](https://imgur.com/a5xThmn.png) 因此你可以增加三個下拉選單,並且你可以參考以下名稱作為下拉選單的名稱。 :::info 1. 字型選單:comboBoxFont 2. 字體大小選單:comboBoxSize 3. 字體樣式選單:comboBoxStyle ::: ## 清單項目如何製作? 下拉選單設定好之後,就要將清單項目塞進選單之中,這時你可能會好奇,要怎麼把清單弄進去呢? 你可能第一個想到的會是:自己輸入進去。字體大小和樣式設定可以這樣做,但字型選單就沒辦法,因為每一個人電腦安裝的字型可能都不一樣,你不可能手動輸入。 所以我們需要能夠取得電腦內部的字型項目,再轉成清單放到下拉選單裡面。 :::success 字型與字體樣式其實都是程式物件,你可以直接放到程式裡面來取用。 ::: # 第二部分:程式碼撰寫 ## 選單初始化 接下來將以下程式碼放到專案之中,請特別注意,方法 Form1() 你只需要加入第 7、8、9 三行即可。剩下的程式則是要複製再貼上。 再測試程式,你應該可以點選下拉選單,就可以看到選項。 ```csharp= public Form1() { InitializeComponent(); // 加入以下三行 InitializeFontComboBox(); InitializeFontSizeComboBox(); InitializeFontStyleComboBox(); } // 初始化字體下拉選單 private void InitializeFontComboBox() { // 將所有系統字體名稱添加到字體選擇框中 foreach (FontFamily font in FontFamily.Families) { comboBoxFont.Items.Add(font.Name); } // 設置預設選中的項目為第一個字體 comboBoxFont.SelectedIndex = 0; } // 初始化字體大小下拉選單 private void InitializeFontSizeComboBox() { // 從8開始,每次增加2,直到72,將這些數值添加到字體大小選擇框中 for (int i = 8; i <= 72; i += 2) { comboBoxSize.Items.Add(i); } // 設置預設選中的項目為第三個大小,即12字體大小 comboBoxSize.SelectedIndex = 2; } // 初始化字體樣式下拉選單 private void InitializeFontStyleComboBox() { // 將不同的字體樣式添加到字體樣式選擇框中 comboBoxStyle.Items.Add(FontStyle.Regular.ToString()); // 正常 comboBoxStyle.Items.Add(FontStyle.Bold.ToString()); // 粗體 comboBoxStyle.Items.Add(FontStyle.Italic.ToString()); // 斜體 comboBoxStyle.Items.Add(FontStyle.Underline.ToString()); // 底線 comboBoxStyle.Items.Add(FontStyle.Strikeout.ToString()); // 刪除線 // 設置預設選中的項目為第一個樣式,即正常字體 comboBoxStyle.SelectedIndex = 0; } ``` 1. 字型選單 ![](https://imgur.com/9kVFsjs.png) 字型選單的項目,其實是擷取電腦內部的字型項目,然後使用迴圈將字型項目一個一個加入(Items.Add())到下拉選單之中。 SelectedIndex = 0 則是指,預設項目為第一個項目,如果沒有這行程式碼,項目會看起來沒有東西。 2. 字體大小選單 ![](https://imgur.com/CGgPTAo.png) 字體大小選單的設計反而很簡單,實際上就是把從數字 8 到 72 之間的偶數加入到下拉選單之中,你可以研究一下迴圈是怎麼寫的? 3. 字體樣式選單 ![](https://imgur.com/1plfk0k.png) 字體樣式的加入則是手動一一將各種樣式的程式物件加入,以下是這些程式物件的說明。 1. FontStyle.Regular:標準字體 2. FontStyle.Bold: 粗體 3. FontStyle.Italic:斜體 4. FontStyle.Underline:底線 5. FontStyle.Strikeout:刪除線 ## 文字樣式套用 選單做好之後,我們要能夠在文字反白後,再選擇下拉選單的項目,接著改變文字的樣式。 接下來請加入以下的程式碼片段。 ```csharp= // 這個方法在 comboBox 的選項變更時觸發 private void comboBox_SelectedIndexChanged(object sender, EventArgs e) { // 檢查當前選擇的文字是否有字型,如果有,則進行後續處理 if (rtbText.SelectionFont != null) { // 從下拉選單中獲取選擇的字型、大小和樣式 string selectedFont = comboBoxFont.SelectedItem?.ToString(); string selectedSizeStr = comboBoxSize.SelectedItem?.ToString(); string selectedStyleStr = comboBoxStyle.SelectedItem?.ToString(); // 確保字型、大小和樣式都已選擇 if (selectedFont != null && selectedSizeStr != null && selectedStyleStr != null) { // 將選擇的大小字串轉換為浮點數 float selectedSize = float.Parse(selectedSizeStr); // 將選擇的樣式字串轉換為 FontStyle 枚舉值 FontStyle selectedStyle = (FontStyle)Enum.Parse(typeof(FontStyle), selectedStyleStr); // 獲取當前選擇的文字的字型 Font currentFont = rtbText.SelectionFont; FontStyle newStyle = currentFont.Style; // 檢查是否需要應用新的樣式,並更新樣式 if (comboBoxStyle.SelectedItem.ToString() == FontStyle.Bold.ToString()) newStyle = FontStyle.Bold; else if (comboBoxStyle.SelectedItem.ToString() == FontStyle.Italic.ToString()) newStyle = FontStyle.Italic; else if (comboBoxStyle.SelectedItem.ToString() == FontStyle.Underline.ToString()) newStyle = FontStyle.Underline; else if (comboBoxStyle.SelectedItem.ToString() == FontStyle.Strikeout.ToString()) newStyle = FontStyle.Strikeout; else newStyle = FontStyle.Regular; // 創建新的字型並應用到選擇的文字 Font newFont = new Font(selectedFont, selectedSize, newStyle); rtbText.SelectionFont = newFont; } } } ``` 你可能會好奇,那麼三個下拉選單的事件綁定呢?請在這三個下拉選單的事件清單裡,找到「**當選擇項目不同時(SelectedIndexChanged)**」,這時請不要立刻點兩下做事件綁定,我們先點選旁邊的箭頭,把這個清單打開,你應該可以找到「comboBox_SelectedIndexChanged」這個項目,就像下圖的樣子。 ![](https://imgur.com/n4SNTf1.png) 三個下拉選單都要做一樣的事情,這時你或許就可以理解,這樣的做法等於是當三個選單選擇項目時,都要執行上方程式碼的意思。如果你選擇特定字型、字體大小與樣式,就會將它們套用在文字裡。 ## 小修正 這時你可能會發現,當你選擇一段文字反白,然後選擇想要修改的字型、字體大小與樣式,但是文字反白卻消失了,現在我們要把這個小問題給修正一下。 ```csharp= private int selectionStart = 0; // 記錄文字反白的起點 private int selectionLength = 0; // 記錄文字反白的長度 private void comboBox_SelectedIndexChanged(object sender, EventArgs e) { // 保存當前選擇的文字起始位置和長度 selectionStart = rtbText.SelectionStart; selectionLength = rtbText.SelectionLength; // 確保當前選擇的文字具有字型 if (rtbText.SelectionFont != null) { // 從下拉選單中獲取選擇的字型、大小和樣式 string selectedFont = comboBoxFont.SelectedItem?.ToString(); string selectedSizeStr = comboBoxSize.SelectedItem?.ToString(); string selectedStyleStr = comboBoxStyle.SelectedItem?.ToString(); // 確保字型、大小和樣式都已選擇 if (selectedFont != null && selectedSizeStr != null && selectedStyleStr != null) { // 將選擇的大小字串轉換為浮點數 float selectedSize = float.Parse(selectedSizeStr); // 將選擇的樣式字串轉換為 FontStyle 枚舉值 FontStyle selectedStyle = (FontStyle)Enum.Parse(typeof(FontStyle), selectedStyleStr); // 獲取當前選擇的文字的字型 Font currentFont = rtbText.SelectionFont; FontStyle newStyle = currentFont.Style; // 檢查是否需要應用新的樣式,並更新樣式 if (comboBoxStyle.SelectedItem.ToString() == FontStyle.Bold.ToString()) newStyle = FontStyle.Bold; else if (comboBoxStyle.SelectedItem.ToString() == FontStyle.Italic.ToString()) newStyle = FontStyle.Italic; else if (comboBoxStyle.SelectedItem.ToString() == FontStyle.Underline.ToString()) newStyle = FontStyle.Underline; else if (comboBoxStyle.SelectedItem.ToString() == FontStyle.Strikeout.ToString()) newStyle = FontStyle.Strikeout; else newStyle = FontStyle.Regular; // 創建新的字型並應用到選擇的文字 Font newFont = new Font(selectedFont, selectedSize, newStyle); rtbText.SelectionFont = newFont; } } // 恢復選擇狀態 rtbText.Focus(); rtbText.Select(selectionStart, selectionLength); } ``` 修正後的程式碼的主要是保存和恢復在「rtbText」中選擇的文字反白範圍,這在需要對文字進行某些操作後(如修改文本格式、顏色等)仍能保持使用者所選擇反白文字範圍時非常有用。 以上程式碼的說明,首先你要將第 1 與 2 行的全域變數宣告出來。分別是用來保存文字反白選擇的文字起始位置(SelectionStart)和長度(SelectionLength)。 接著我們在修改文字樣式前,會在第 7 與 8 行記錄目前選擇的文字反白範圍。 文字樣式修改後,在第 49 與 50 行,將要控制的「rtbText」豐富文字框取得控制,再將原本紀錄的文字起始位置和長度重新反白起來。 這樣就能夠讓文字反白範圍一直顯示在「rtbText」之中。 # 完整程式碼 :::spoiler ```csharp= // 初始化字體下拉選單 private void InitializeFontComboBox() { // 將所有系統字體名稱添加到字體選擇框中 foreach (FontFamily font in FontFamily.Families) { comboBoxFont.Items.Add(font.Name); } // 設置預設選中的項目為第一個字體 comboBoxFont.SelectedIndex = 0; } // 初始化字體大小下拉選單 private void InitializeFontSizeComboBox() { // 從8開始,每次增加2,直到72,將這些數值添加到字體大小選擇框中 for (int i = 8; i <= 72; i += 2) { comboBoxSize.Items.Add(i); } // 設置預設選中的項目為第三個大小,即12字體大小 comboBoxSize.SelectedIndex = 2; } // 初始化字體樣式下拉選單 private void InitializeFontStyleComboBox() { // 將不同的字體樣式添加到字體樣式選擇框中 comboBoxStyle.Items.Add(FontStyle.Regular.ToString()); // 正常 comboBoxStyle.Items.Add(FontStyle.Bold.ToString()); // 粗體 comboBoxStyle.Items.Add(FontStyle.Italic.ToString()); // 斜體 comboBoxStyle.Items.Add(FontStyle.Underline.ToString()); // 底線 comboBoxStyle.Items.Add(FontStyle.Strikeout.ToString()); // 刪除線 // 設置預設選中的項目為第一個樣式,即正常字體 comboBoxStyle.SelectedIndex = 0; } private int selectionStart = 0; // 記錄文字反白的起點 private int selectionLength = 0; // 記錄文字反白的長度 // 這個方法在 comboBox 的選項變更時觸發 private void comboBox_SelectedIndexChanged(object sender, EventArgs e) { // 檢查當前選擇的文字是否有字型,如果有,則進行後續處理 if (rtbText.SelectionFont != null) { // 從下拉選單中獲取選擇的字型、大小和樣式 string selectedFont = comboBoxFont.SelectedItem?.ToString(); string selectedSizeStr = comboBoxSize.SelectedItem?.ToString(); string selectedStyleStr = comboBoxStyle.SelectedItem?.ToString(); // 確保字型、大小和樣式都已選擇 if (selectedFont != null && selectedSizeStr != null && selectedStyleStr != null) { // 將選擇的大小字串轉換為浮點數 float selectedSize = float.Parse(selectedSizeStr); // 將選擇的樣式字串轉換為 FontStyle 枚舉值 FontStyle selectedStyle = (FontStyle)Enum.Parse(typeof(FontStyle), selectedStyleStr); // 獲取當前選擇的文字的字型 Font currentFont = rtbText.SelectionFont; FontStyle newStyle = currentFont.Style; // 檢查是否需要應用新的樣式,並更新樣式 if (comboBoxStyle.SelectedItem.ToString() == FontStyle.Bold.ToString()) newStyle = FontStyle.Bold; else if (comboBoxStyle.SelectedItem.ToString() == FontStyle.Italic.ToString()) newStyle = FontStyle.Italic; else if (comboBoxStyle.SelectedItem.ToString() == FontStyle.Underline.ToString()) newStyle = FontStyle.Underline; else if (comboBoxStyle.SelectedItem.ToString() == FontStyle.Strikeout.ToString()) newStyle = FontStyle.Strikeout; else newStyle = FontStyle.Regular; // 創建新的字型並應用到選擇的文字 Font newFont = new Font(selectedFont, selectedSize, newStyle); rtbText.SelectionFont = newFont; } } } ``` :::