Procedimiento para modificar la entrada de teclado en un control estándar

Windows Forms permite consumir y modificar la entrada de teclado. Consumir una tecla es controlar una tecla dentro de un método o controlador de eventos para que otros métodos y eventos más abajo en la cola de mensajes no reciban el valor de la tecla. Modificar una tecla es modificar el valor de una tecla para que los métodos y controladores de eventos más abajo en la cola de mensajes reciban un valor de tecla diferente. En este tema se muestra cómo realizar estas tareas.

Para consumir una tecla

  • En un controlador de eventos KeyPress, establezca la propiedad Handled de la clase KeyPressEventArgs en true.

    O bien

    En un controlador de eventos KeyDown, establezca la propiedad Handled de la clase KeyEventArgs en true.

    Nota:

    Establecer la propiedad Handled en el controlador de eventos KeyDown no impide que los eventos KeyPress y KeyUp se generen para la pulsación de tecla actual. Use la propiedad SuppressKeyPress para este propósito.

    El ejemplo siguiente es un extracto de una instrucción switch que examina la propiedad KeyChar de KeyPressEventArgs recibido por un controlador de eventos KeyPress. Este código consume las teclas de caracteres 'A' y 'a'.

    // Consume 'A' and 'a'.
    case (char)65:
    case (char)97:
        MessageBox.Show("Control.KeyPress: '" +
            e.KeyChar.ToString() + "' consumed.");
        e.Handled = true;
        break;
    
    ' Consume 'A' and 'a'.
    Case ChrW(65), ChrW(97)
        MessageBox.Show(("Control.KeyPress: '" + _
            e.KeyChar.ToString() + "' consumed."))
        e.Handled = True
    

Para modificar una tecla de carácter estándar

  • En un controlador de eventos KeyPress, establezca la propiedad KeyChar de la clase KeyPressEventArgs en el valor de la nueva tecla de carácter.

    El ejemplo siguiente es un extracto de una instrucción switch que modifica 'B' por 'A' y 'b' por 'a'. Tenga en cuenta que la propiedad Handled del parámetro KeyPressEventArgs está establecida en false, por lo que el nuevo valor de tecla se propaga a otros métodos y eventos de la cola de mensajes.

    // Detect 'B', modify it to 'A', and forward the key.
    case (char)66:
        MessageBox.Show("Control.KeyPress: '" +
            e.KeyChar.ToString() + "' replaced by 'A'.");
        e.KeyChar = (char)65;
        e.Handled = false;
        break;
    
    // Detect 'b', modify it to 'a', and forward the key.
    case (char)98:
        MessageBox.Show("Control.KeyPress: '" +
            e.KeyChar.ToString() + "' replaced by 'a'.");
        e.KeyChar = (char)97;
        e.Handled = false;
        break;
    
        ' Modify 'B' to 'A' and forward the key.
    Case ChrW(66)
        MessageBox.Show(("Control.KeyPress: '" + _
            e.KeyChar.ToString() + "' replaced by 'A'."))
        e.KeyChar = ChrW(65)
        e.Handled = False
    
        ' Modify 'b' to 'a' and forward the key.
    Case ChrW(98)
        MessageBox.Show(("Control.KeyPress: '" + _
            e.KeyChar.ToString() + "' replaced by 'a'."))
        e.KeyChar = ChrW(97)
        e.Handled = False
    

Para modificar una tecla que no es de carácter

  • Invalide un método Control que procesa los mensajes de Windows, detecte el mensaje WM_KEYDOWN o WM_SYSKEYDOWN y establezca la propiedad WParam del parámetro Message en el valor Keys que representa la nueva tecla que no es de carácter.

    En el ejemplo de código siguiente se muestra cómo invalidar el método PreProcessMessage de un control para detectar las teclas F1 a F9 y modificar cualquier pulsación de tecla de F3 por F1. Para obtener más información sobre los métodos Control que se pueden invalidar para interceptar los mensajes del teclado, consulte Datos introducidos por el usuario en una aplicación de Windows Forms y Funcionamiento de las entradas mediante teclado.

    // Detect F1 through F9 during preprocessing and modify F3.
    public override bool PreProcessMessage(ref Message m)
    {
        if (m.Msg == WM_KEYDOWN)
        {
            Keys keyCode = (Keys)m.WParam & Keys.KeyCode;
    
            // Detect F1 through F9.
            switch (keyCode)
            {
                case Keys.F1:
                case Keys.F2:
                case Keys.F3:
                case Keys.F4:
                case Keys.F5:
                case Keys.F6:
                case Keys.F7:
                case Keys.F8:
                case Keys.F9:
    
                    MessageBox.Show("Control.PreProcessMessage: '" +
                      keyCode.ToString() + "' pressed.");
    
                    // Replace F3 with F1, so that ProcessKeyMessage will
                    // receive F1 instead of F3.
                    if (keyCode == Keys.F3)
                    {
                        m.WParam = (IntPtr)Keys.F1;
                        MessageBox.Show("Control.PreProcessMessage: '" +
                            keyCode.ToString() + "' replaced by F1.");
                    }
                    break;
            }
        }
    
        // Send all other messages to the base method.
        return base.PreProcessMessage(ref m);
    }
    
    ' Detect F1 through F9 during preprocessing and modify F3.
    Public Overrides Function PreProcessMessage(ByRef m As Message) _
        As Boolean
    
        If m.Msg = WM_KEYDOWN Then
            Dim keyCode As Keys = CType(m.WParam, Keys) And Keys.KeyCode
    
            ' Detect F1 through F9.
            Select Case keyCode
                Case Keys.F1, Keys.F2, Keys.F3, Keys.F4, Keys.F5, _
                     Keys.F6, Keys.F7, Keys.F8, Keys.F9
    
                    MessageBox.Show(("Control.PreProcessMessage: '" + _
                        keyCode.ToString() + "' pressed."))
    
                    ' Replace F3 with F1, so that ProcessKeyMessage will  
                    ' receive F1 instead of F3.
                    If keyCode = Keys.F3 Then
                        m.WParam = CType(Keys.F1, IntPtr)
                        MessageBox.Show(("Control.PreProcessMessage: '" + _
                            keyCode.ToString() + "' replaced by F1."))
                    End If
            End Select
        End If
    
        ' Send all other messages to the base method.
        Return MyBase.PreProcessMessage(m)
    End Function
    

Ejemplo

El ejemplo de código siguiente es la aplicación completa de los ejemplos de código de las secciones anteriores. La aplicación usa un control personalizado derivado de la clase TextBox para consumir y modificar la entrada de teclado.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace KeyboardInput
{
    class Form1 : Form
    {
        // The following Windows message value is defined in Winuser.h.
        private int WM_KEYDOWN = 0x100;
        CustomTextBox CustomTextBox1 = new CustomTextBox();

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

        public Form1()
        {
            this.AutoSize = true;
            this.Controls.Add(CustomTextBox1);
            CustomTextBox1.KeyPress +=
                new KeyPressEventHandler(CustomTextBox1_KeyPress);
        }

        // Consume and modify several character keys.
        void CustomTextBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            switch (e.KeyChar)
            {
                // Consume 'A' and 'a'.
                case (char)65:
                case (char)97:
                    MessageBox.Show("Control.KeyPress: '" +
                        e.KeyChar.ToString() + "' consumed.");
                    e.Handled = true;
                    break;

                // Detect 'B', modify it to 'A', and forward the key.
                case (char)66:
                    MessageBox.Show("Control.KeyPress: '" +
                        e.KeyChar.ToString() + "' replaced by 'A'.");
                    e.KeyChar = (char)65;
                    e.Handled = false;
                    break;

                // Detect 'b', modify it to 'a', and forward the key.
                case (char)98:
                    MessageBox.Show("Control.KeyPress: '" +
                        e.KeyChar.ToString() + "' replaced by 'a'.");
                    e.KeyChar = (char)97;
                    e.Handled = false;
                    break;
            }
        }
    }
    
    public class CustomTextBox : TextBox
    {
        // The following Windows message value is defined in Winuser.h.
        private int WM_KEYDOWN = 0x100;

        public CustomTextBox()
        {
            this.Size = new Size(100, 100);
            this.AutoSize = false;
        }

        // Detect F1 through F9 during preprocessing and modify F3.
        public override bool PreProcessMessage(ref Message m)
        {
            if (m.Msg == WM_KEYDOWN)
            {
                Keys keyCode = (Keys)m.WParam & Keys.KeyCode;

                // Detect F1 through F9.
                switch (keyCode)
                {
                    case Keys.F1:
                    case Keys.F2:
                    case Keys.F3:
                    case Keys.F4:
                    case Keys.F5:
                    case Keys.F6:
                    case Keys.F7:
                    case Keys.F8:
                    case Keys.F9:

                        MessageBox.Show("Control.PreProcessMessage: '" +
                          keyCode.ToString() + "' pressed.");

                        // Replace F3 with F1, so that ProcessKeyMessage will
                        // receive F1 instead of F3.
                        if (keyCode == Keys.F3)
                        {
                            m.WParam = (IntPtr)Keys.F1;
                            MessageBox.Show("Control.PreProcessMessage: '" +
                                keyCode.ToString() + "' replaced by F1.");
                        }
                        break;
                }
            }

            // Send all other messages to the base method.
            return base.PreProcessMessage(ref m);
        }

        // Detect F1 through F9 during processing.
        protected override bool ProcessKeyMessage(ref Message m)
        {
            if (m.Msg == WM_KEYDOWN)
            {
                Keys keyCode = (Keys)m.WParam & Keys.KeyCode;

                // Detect F1 through F9.
                switch (keyCode)
                {
                    case Keys.F1:
                    case Keys.F2:
                    case Keys.F3:
                    case Keys.F4:
                    case Keys.F5:
                    case Keys.F6:
                    case Keys.F7:
                    case Keys.F8:
                    case Keys.F9:

                        MessageBox.Show("Control.ProcessKeyMessage: '" +
                          keyCode.ToString() + "' pressed.");
                        break;
                }
            }

            // Send all messages to the base method.
            return base.ProcessKeyMessage(ref m);
        }
    }
}
Imports System.Drawing
Imports System.Security
Imports System.Security.Permissions
Imports System.Windows.Forms

Namespace KeyboardInput
    Class Form1
        Inherits Form

        ' The following Windows message value is defined in Winuser.h.
        Private WM_KEYDOWN As Integer = &H100
        Private WithEvents CustomTextBox1 As New CustomTextBox()

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

        Public Sub New()
            Me.AutoSize = True
            Me.Controls.Add(CustomTextBox1)
        End Sub

        ' Consume and modify several character keys.
        Sub CustomTextBox1_KeyPress(ByVal sender As Object, _
            ByVal e As KeyPressEventArgs) Handles CustomTextBox1.KeyPress

            Select Case e.KeyChar

                ' Consume 'A' and 'a'.
                Case ChrW(65), ChrW(97)
                    MessageBox.Show(("Control.KeyPress: '" + _
                        e.KeyChar.ToString() + "' consumed."))
                    e.Handled = True

                    ' Modify 'B' to 'A' and forward the key.
                Case ChrW(66)
                    MessageBox.Show(("Control.KeyPress: '" + _
                        e.KeyChar.ToString() + "' replaced by 'A'."))
                    e.KeyChar = ChrW(65)
                    e.Handled = False

                    ' Modify 'b' to 'a' and forward the key.
                Case ChrW(98)
                    MessageBox.Show(("Control.KeyPress: '" + _
                        e.KeyChar.ToString() + "' replaced by 'a'."))
                    e.KeyChar = ChrW(97)
                    e.Handled = False
            End Select
        End Sub
    End Class

    Public Class CustomTextBox
        Inherits TextBox

        ' The following Windows message value is defined in Winuser.h.
        Private WM_KEYDOWN As Integer = &H100

        Public Sub New()
            Me.Size = New Size(100, 100)
            Me.AutoSize = False
        End Sub

        ' Detect F1 through F9 during preprocessing and modify F3.
        Public Overrides Function PreProcessMessage(ByRef m As Message) _
            As Boolean

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

                ' Detect F1 through F9.
                Select Case keyCode
                    Case Keys.F1, Keys.F2, Keys.F3, Keys.F4, Keys.F5, _
                         Keys.F6, Keys.F7, Keys.F8, Keys.F9

                        MessageBox.Show(("Control.PreProcessMessage: '" + _
                            keyCode.ToString() + "' pressed."))

                        ' Replace F3 with F1, so that ProcessKeyMessage will  
                        ' receive F1 instead of F3.
                        If keyCode = Keys.F3 Then
                            m.WParam = CType(Keys.F1, IntPtr)
                            MessageBox.Show(("Control.PreProcessMessage: '" + _
                                keyCode.ToString() + "' replaced by F1."))
                        End If
                End Select
            End If

            ' Send all other messages to the base method.
            Return MyBase.PreProcessMessage(m)
        End Function

        ' Detect F1 through F9 during processing.
        Protected Overrides Function ProcessKeyMessage(ByRef m As Message) _
            As Boolean

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

                ' Detect F1 through F9.
                Select Case keyCode
                    Case Keys.F1, Keys.F2, Keys.F3, Keys.F4, Keys.F5, _
                         Keys.F6, Keys.F7, Keys.F8, Keys.F9

                        MessageBox.Show(("Control.ProcessKeyMessage: '" + _
                            keyCode.ToString() + "' pressed."))
                End Select
            End If

            ' Send all messages to the base method.
            Return MyBase.ProcessKeyMessage(m)
        End Function

    End Class
End Namespace

Compilar el código

Para este ejemplo se necesita:

  • Referencias a los ensamblados System, System.Drawing y System.Windows.Forms.

Vea también