共用方式為


HOW TO:處理表單層級的鍵盤輸入

更新:2007 年 11 月

Windows Form 可讓您在鍵盤訊息到達控制項之前,在表單層級處理此訊息。本說明主題將示範如何完成這項工作。

若要在表單層級處理鍵盤訊息

  • 處理啟動表單的 KeyPressKeyDown 事件,並將表單的 KeyPreview 屬性設為 true,這樣表單就會在鍵盤訊息到達表單上的任何控制項之前先接收鍵盤訊息。下列程式碼範例會先偵測所有數字鍵,然後使用 '1'、'4' 和 '7',藉此處理 KeyPress 事件。

    ' Detect all numeric characters at the form level and consume 1, 
    ' 4, and 7. Note that Form.KeyPreview must be set to true for this
    ' event handler to be called.
    Sub Form1_KeyPress(ByVal sender As Object, _
        ByVal e As KeyPressEventArgs) Handles Me.KeyPress
    
        If e.KeyChar >= ChrW(48) And e.KeyChar <= ChrW(57) Then
            MessageBox.Show(("Form.KeyPress: '" + _
                e.KeyChar.ToString() + "' pressed."))
    
            Select Case e.KeyChar
                Case ChrW(49), ChrW(52), ChrW(55)
                    MessageBox.Show(("Form.KeyPress: '" + _
                        e.KeyChar.ToString() + "' consumed."))
                    e.Handled = True
            End Select
        End If
    End Sub
    
    // Detect all numeric characters at the form level and consume 1, 
    // 4, and 7. Note that Form.KeyPreview must be set to true for this
    // event handler to be called.
    void Form1_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (e.KeyChar >= 48 && e.KeyChar <= 57)
        {
            MessageBox.Show("Form.KeyPress: '" +
                e.KeyChar.ToString() + "' pressed.");
    
            switch (e.KeyChar)
            {
                case (char)49:
                case (char)52:
                case (char)55:
                    MessageBox.Show("Form.KeyPress: '" +
                        e.KeyChar.ToString() + "' consumed.");
                    e.Handled = true;
                    break;
            }
        }
    }
    
        // Detect all numeric characters at the form level and consume 1,
        // 4, and 7. Note that Form.KeyPreview must be set to true for this
        // event handler to be called.
    private:
        void Form1_KeyPress(Object^ sender, KeyPressEventArgs^ e)
        {
            if ((e->KeyChar >= '0') && (e->KeyChar <= '9'))
            {
                MessageBox::Show("Form.KeyPress: '" +
                    e->KeyChar.ToString() + "' pressed.");
    
                switch (e->KeyChar)
                {
                case '1':
                case '4':
                case '7':
                    MessageBox::Show("Form.KeyPress: '" +
                        e->KeyChar.ToString() + "' consumed.");
                    e->Handled = true;
                    break;
                }
            }
        }
    

範例

下列程式碼範例是上述範例的完整應用程式。此應用程式包含了 TextBox 以及其他幾個控制項,可讓您將焦點從 TextBox 身上移走。主 FormKeyPress 事件會使用 '1'、'4' 和 '7',而 TextBoxKeyPress 事件則會使用 '2'、'5' 和 '8' 同時顯示其餘的按鍵。請比較這兩種情況下的輸出:當您在 TextBox 具有焦點時按下了某個數字鍵所得到的 MessageBox 輸出,以及當您在焦點是位於其他任何一個控制項上時按下了某個數字鍵所得到的 MessageBox 輸出。

Imports System
Imports System.Drawing
Imports System.Windows.Forms

Namespace KeyboardInputForm

     Class Form1
      Inherits Form

        Private WithEvents TextBox1 As New TextBox()

      <STAThread()> _
      Public Shared Sub Main()
         Application.EnableVisualStyles()
         Application.Run(New Form1())
      End Sub

      Public Sub New()
         Me.AutoSize = True

         Dim panel As New FlowLayoutPanel()
         panel.AutoSize = True
         panel.FlowDirection = FlowDirection.TopDown
         panel.Controls.Add(TextBox1)
         Me.Controls.Add(panel)

         Me.KeyPreview = True
        End Sub

        ' Detect all numeric characters at the form level and consume 1, 
        ' 4, and 7. Note that Form.KeyPreview must be set to true for this
        ' event handler to be called.
        Sub Form1_KeyPress(ByVal sender As Object, _
            ByVal e As KeyPressEventArgs) Handles Me.KeyPress

            If e.KeyChar >= ChrW(48) And e.KeyChar <= ChrW(57) Then
                MessageBox.Show(("Form.KeyPress: '" + _
                    e.KeyChar.ToString() + "' pressed."))

                Select Case e.KeyChar
                    Case ChrW(49), ChrW(52), ChrW(55)
                        MessageBox.Show(("Form.KeyPress: '" + _
                            e.KeyChar.ToString() + "' consumed."))
                        e.Handled = True
                End Select
            End If
        End Sub

      ' Detect all numeric characters at the TextBox level and consume  
      ' 2, 5, and 8.
      Sub TextBox1_KeyPress(ByVal sender As Object, _
          ByVal e As KeyPressEventArgs) Handles TextBox1.KeyPress

         If e.KeyChar >= ChrW(48) And e.KeyChar <= ChrW(57) Then
            MessageBox.Show(("Control.KeyPress: '" + _
                e.KeyChar.ToString() + "' pressed."))

            Select Case e.KeyChar
               Case ChrW(50), ChrW(53), ChrW(56)
                  MessageBox.Show(("Control.KeyPress: '" + _
                      e.KeyChar.ToString() + "' consumed."))
                  e.Handled = True
            End Select
         End If
      End Sub

   End Class
End Namespace
using System;
using System.Drawing;
using System.Windows.Forms;

namespace KeyboardInputForm
{
    class Form1 : Form
    {
        TextBox TextBox1 = new TextBox();

        [STAThread]
        public static void Main()
        {
            Application.EnableVisualStyles();
            Application.Run(new Form1());
        }

        public Form1()
        {
            this.AutoSize = true;

            FlowLayoutPanel panel = new FlowLayoutPanel();
            panel.AutoSize = true;
            panel.FlowDirection = FlowDirection.TopDown;
            panel.Controls.Add(TextBox1);
            this.Controls.Add(panel);

            this.KeyPreview = true;
            this.KeyPress +=
                new KeyPressEventHandler(Form1_KeyPress);
            TextBox1.KeyPress +=
                new KeyPressEventHandler(TextBox1_KeyPress);
        }

        // Detect all numeric characters at the form level and consume 1, 
        // 4, and 7. Note that Form.KeyPreview must be set to true for this
        // event handler to be called.
        void Form1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar >= 48 && e.KeyChar <= 57)
            {
                MessageBox.Show("Form.KeyPress: '" +
                    e.KeyChar.ToString() + "' pressed.");

                switch (e.KeyChar)
                {
                    case (char)49:
                    case (char)52:
                    case (char)55:
                        MessageBox.Show("Form.KeyPress: '" +
                            e.KeyChar.ToString() + "' consumed.");
                        e.Handled = true;
                        break;
                }
            }
        }

        // Detect all numeric characters at the TextBox level and consume  
        // 2, 5, and 8.
        void TextBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar >= 48 && e.KeyChar <= 57)
            {
                MessageBox.Show("Control.KeyPress: '" +
                    e.KeyChar.ToString() + "' pressed.");

                switch (e.KeyChar)
                {
                    case (char)50:
                    case (char)53:
                    case (char)56:
                        MessageBox.Show("Control.KeyPress: '" +
                            e.KeyChar.ToString() + "' consumed.");
                        e.Handled = true;
                        break;
                }
            }
        }
    }
}
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>
#using <System.dll>

using namespace System;
using namespace System::Drawing;
using namespace System::Windows::Forms;
using namespace System::Security::Permissions;

namespace KeyboardInputForm
{
    public ref class Form1 sealed: public Form, public IMessageFilter
    {
        // The following Windows message value is defined in Winuser.h.
    private:
        static const int WM_KEYDOWN = 0x100;
    private:
        TextBox^ inputTextBox;
    public:
        Form1()
        {
            inputTextBox = gcnew TextBox();
            this->AutoSize = true;
            Application::AddMessageFilter(this);
            FlowLayoutPanel^ panel = gcnew FlowLayoutPanel();
            panel->AutoSize = true;
            panel->FlowDirection = FlowDirection::TopDown;
            panel->Controls->Add(gcnew Button());
            panel->Controls->Add(gcnew RadioButton());
            panel->Controls->Add(inputTextBox);
            this->Controls->Add(panel);
            this->KeyPreview = true;
            this->KeyPress +=
                gcnew KeyPressEventHandler(this, &Form1::Form1_KeyPress);
            inputTextBox->KeyPress +=
                gcnew KeyPressEventHandler(this,
                &Form1::inputTextBox_KeyPress);
        }

        // Detect all numeric characters at the
        // application level and consume 0.
        [SecurityPermission(SecurityAction::LinkDemand,
            Flags=SecurityPermissionFlag::UnmanagedCode)]
        virtual bool PreFilterMessage(Message% m)
        {
            // Detect key down messages.
            if (m.Msg == WM_KEYDOWN)
            {
                Keys keyCode =  (Keys)((int)m.WParam) & Keys::KeyCode;
                // Determine whether the keystroke is a number from the top of
                // the keyboard, or a number from the keypad.
                if (((keyCode >= Keys::D0) && (keyCode <= Keys::D9))
                    ||((keyCode >= Keys::NumPad0)
                    && (keyCode <= Keys::NumPad9)))
                {
                    MessageBox::Show(
                        "IMessageFilter.PreFilterMessage: '" +
                        keyCode.ToString() + "' pressed.");

                    if ((keyCode == Keys::D0) || (keyCode == Keys::NumPad0))
                    {
                        MessageBox::Show(
                            "IMessageFilter.PreFilterMessage: '" +
                            keyCode.ToString() + "' consumed.");
                        return true;
                    }
                }
            }

            // Forward all other messages.
            return false;
        }

        // Detect all numeric characters at the form level and consume 1,
        // 4, and 7. Note that Form.KeyPreview must be set to true for this
        // event handler to be called.
    private:
        void Form1_KeyPress(Object^ sender, KeyPressEventArgs^ e)
        {
            if ((e->KeyChar >= '0') && (e->KeyChar <= '9'))
            {
                MessageBox::Show("Form.KeyPress: '" +
                    e->KeyChar.ToString() + "' pressed.");

                switch (e->KeyChar)
                {
                case '1':
                case '4':
                case '7':
                    MessageBox::Show("Form.KeyPress: '" +
                        e->KeyChar.ToString() + "' consumed.");
                    e->Handled = true;
                    break;
                }
            }
        }

        // Detect all numeric characters at the TextBox level and consume
        // 2, 5, and 8.
    private:
        void inputTextBox_KeyPress(Object^ sender, KeyPressEventArgs^ e)
        {
            if ((e->KeyChar >= '0') && (e->KeyChar <= '9'))
            {
                MessageBox::Show("Control.KeyPress: '" +
                    e->KeyChar.ToString() + "' pressed.");

                switch (e->KeyChar)
                {
                case '2':
                case '5':
                case '8':
                    MessageBox::Show("Control.KeyPress: '" +
                        e->KeyChar.ToString() + "' consumed.");
                    e->Handled = true;
                    break;
                }
            }
        }
    };
}

[STAThread]
int main()
{
    Application::EnableVisualStyles();
    Application::Run(gcnew KeyboardInputForm::Form1());
}

編譯程式碼

這項範例需要:

  • System、System.Drawing 和 System.Windows.Forms 組件的參考。

如需從 Visual Basic 或 Visual C# 的命令列建置這個範例的詳細資訊,請參閱從命令列建置 (Visual Basic)使用 csc.exe 建置命令列。您也可以透過將程式碼貼入新的專案,在 Visual Studio 中建置此範例。

請參閱

其他資源

Windows Form 應用程式中的鍵盤輸入