C# WinForm 自訂義快捷鍵

目錄:

Alt + 英文 快捷鍵

Button 中預設要加入快捷鍵很簡單,就是在 Text 文字中要設定快捷鍵的文字前面加上 & 符號即可,按下 Alt + 英文就會觸發 Button 的 Click 事件。

使用下面的程式在按下鍵盤上的 Alt 時,第一個英文字 b 下面會顯示一條底線,代表這個按鈕的快捷鍵就是 Alt + B 按下 Alt + B 後就會觸發 Button 的 Click 事件,彈出對話框
  
button1.Text = "&button1";
button1.Click += (sender, e) => { MessageBox.Show("button1 Click"); };



如果要多個快捷鍵也可以增加多個 & 符號
例如下面的範例使用 Alt + B 或是 Alt + T 都可以觸發 button1 的 Click 事件,但是在有多個「&」的情況下,只會顯示最後一個 & 符號的快捷鍵
  
button1.Text = "&bu&tton1";
button1.Click += (sender, e) => { MessageBox.Show("button1 Click"); };



「&」後方如果是中文,在按下 Alt 後會正常顯示底線,但是快捷鍵並不能正常被觸發

中文名稱最好的方式就是在後面加上括號,在括號裡面放上快捷鍵
  
button1.Text = "按鈕 (&B)";



自訂快捷鍵

如果要使用自訂快捷鍵需要先加上這行:
  
KeyPreview = true;


「KeyPreview 屬性」可以簡單理解為 Form 會全域接收按鍵事件, 當 Form 處理完按鍵事件之後,當前焦點的控制項才會接收到按鍵事件並進行處理。
為什麼要把 KeyPreview 屬性設定為 true ? 因為我們通常會把鍵盤事件寫在 Form1 的鍵盤事件中,這樣只要焦點在其他物件上就接收不到。
那為什麼要寫在 Form1 的鍵盤事件中呢?因為假設寫在 button1 的鍵盤事件,只要焦點不在 button1 上,就不會接收到按鍵事件,所以才會寫在 Form1 上,讓每個控制項都能夠共用鍵盤事件。

設定 button1 的快捷鍵為 Ctrl + B:
  
        KeyPreview = true;
        this.KeyDown += (sender, e) =>
        {
            if (e.KeyData == (Keys.B | Keys.Control))
            {
                button1.PerformClick();
            }
        };


設定 button1 的快捷鍵為 Ctrl + Shift + B:
  
        KeyPreview = true;
        this.KeyDown += (sender, e) =>
        {
            if (e.KeyData == (Keys.B | Keys.Control | Keys.Shift))
            {
                button1.PerformClick();
            }
        };


補充: 有些人喜歡用 e.KeyCode 來判斷按下的按鍵,但是這樣可能會沒有判斷到「控制鍵」有沒有被按下
  
        KeyPreview = true;
        this.KeyDown += (sender, e) =>
        {
            if (e.KeyCode == Keys.B)
            {
                // B, Ctrl + B, Ctrl + Shift + B ... 等只要有按下 B 就都會被觸發
            }
            else if (e.KeyCode == Keys.B && !e.Control)
            {
                // 沒有包含控制鍵的 B 才會被觸發
            }
        };



在 TextBox 內忽略鍵盤事件

因為我們有設定下面這行:
  
        KeyPreview = true;


所以在 TextBox 之類的輸入框內也會觸發鍵盤事件。
假設設定了一個快捷鍵 A (不包含 Ctrl, Shift, Alt 等控制鍵),那在 TextBox 中只要按下 A 就會被觸發

解決方式 1:在進入到 TextBox 的時候取消 KeyPreview 屬性,這樣就不會觸發鍵盤事件
  
        textBox1.Enter += (sender, e) => { KeyPreview = false; };
        textBox1.Leave += (sender, e) => { KeyPreview = true; };


解決方式 2:當焦點在 TextBox 上時,不處理鍵盤事件
  
        KeyPreview = true;
        this.KeyDown += (sender, e) =>
        {
            if (textBox1.Focus()) return;

            if (e.KeyData == Keys.B)
            {
                button1.PerformClick();
            }
        };



參考資料:
Form.KeyPreview 屬性
Control.Enter Event
Control.Leave Event

留言