如何修改键盘键事件(Windows 窗体 .NET)

Windows 窗体提供使用和修改键盘输入的功能。 使用键是指处理方法或事件处理程序内的键,以便消息队列更低处的其他方法和事件不会收到键值。 修改键是指修改键的值,以便消息队列更低处的方法和事件处理程序接收不同的键值。 本文演示如何完成这些任务。

重要

面向 .NET 7 和 .NET 6 的桌面指南文档正在撰写中。

使用键

KeyPress 事件处理程序中,将 KeyPressEventArgs 类的 Handled 属性设置为 true

- 或者 -

KeyDown 事件处理程序中,将 KeyEventArgs 类的 Handled 属性设置为 true

注意

设置 KeyDown 事件处理程序中的 Handled 属性不会防止 KeyPressKeyUp 事件因当前按键而引发。 要实现此目的,请使用 SuppressKeyPress 属性。

下面的示例处理 KeyPress 事件以使用 Aa 字符键。 不能在文本框中键入这些键:

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    if (e.KeyChar == 'a' || e.KeyChar == 'A')
        e.Handled = true;
}
Private Sub TextBox1_KeyPress(sender As Object, e As KeyPressEventArgs)
    If e.KeyChar = "a"c Or e.KeyChar = "A"c Then
        e.Handled = True
    End If
End Sub

修改标准字符键

KeyPress 事件处理程序中,将 KeyPressEventArgs 类的 KeyChar 属性设置为新字符键的值。

下面的示例处理 KeyPress 事件以将 Aa 字符键更改为 !

private void textBox2_KeyPress(object sender, KeyPressEventArgs e)
{
    if (e.KeyChar == 'a' || e.KeyChar == 'A')
    {
        e.KeyChar = '!';
        e.Handled = false;
    }
}
Private Sub TextBox2_KeyPress(sender As Object, e As KeyPressEventArgs)
    If e.KeyChar = "a"c Or e.KeyChar = "A"c Then
        e.KeyChar = "!"c
        e.Handled = False
    End If
End Sub

修改非字符键

仅可通过从控件继承并重写 PreProcessMessage 方法来修改非字符按键。 当输入 Message 发送到控件时,将在控件引发事件之前对其进行处理。 可以截获这些消息来修改或阻止它们。

以下代码示例演示了如何使用 Message 参数的 WParam 属性来更改按下的键。 此代码检测从 F1F10 的键,并将该键转换为 09 之间的数字键(其中 F10 映射到 0)。

public override bool PreProcessMessage(ref Message m)
{
    const int WM_KEYDOWN = 0x100;

    if (m.Msg == WM_KEYDOWN)
    {
        Keys keyCode = (Keys)m.WParam & Keys.KeyCode;

        // Detect F1 through F9.
        m.WParam = keyCode switch
        {
            Keys.F1 => (IntPtr)Keys.D1,
            Keys.F2 => (IntPtr)Keys.D2,
            Keys.F3 => (IntPtr)Keys.D3,
            Keys.F4 => (IntPtr)Keys.D4,
            Keys.F5 => (IntPtr)Keys.D5,
            Keys.F6 => (IntPtr)Keys.D6,
            Keys.F7 => (IntPtr)Keys.D7,
            Keys.F8 => (IntPtr)Keys.D8,
            Keys.F9 => (IntPtr)Keys.D9,
            Keys.F10 => (IntPtr)Keys.D0,
            _ => m.WParam
        };
    }

    // Send all other messages to the base method.
    return base.PreProcessMessage(ref m);
}
Public Overrides Function PreProcessMessage(ByRef m As Message) As Boolean

    Const WM_KEYDOWN = &H100

    If m.Msg = WM_KEYDOWN Then
        Dim keyCode As Keys = CType(m.WParam, Keys) And Keys.KeyCode

        Select Case keyCode
            Case Keys.F1 : m.WParam = CType(Keys.D1, IntPtr)
            Case Keys.F2 : m.WParam = CType(Keys.D2, IntPtr)
            Case Keys.F3 : m.WParam = CType(Keys.D3, IntPtr)
            Case Keys.F4 : m.WParam = CType(Keys.D4, IntPtr)
            Case Keys.F5 : m.WParam = CType(Keys.D5, IntPtr)
            Case Keys.F6 : m.WParam = CType(Keys.D6, IntPtr)
            Case Keys.F7 : m.WParam = CType(Keys.D7, IntPtr)
            Case Keys.F8 : m.WParam = CType(Keys.D8, IntPtr)
            Case Keys.F9 : m.WParam = CType(Keys.D9, IntPtr)
            Case Keys.F10 : m.WParam = CType(Keys.D0, IntPtr)
        End Select
    End If

    Return MyBase.PreProcessMessage(m)
End Function

另请参阅