diff --git a/dotnet-desktop-guide/winforms/input-keyboard/how-to-change-key-press.md b/dotnet-desktop-guide/winforms/input-keyboard/how-to-change-key-press.md index 1fd57542b3..cc2ff01aac 100644 --- a/dotnet-desktop-guide/winforms/input-keyboard/how-to-change-key-press.md +++ b/dotnet-desktop-guide/winforms/input-keyboard/how-to-change-key-press.md @@ -1,7 +1,7 @@ --- title: "Modify keyboard key events" description: Learn how to intercept a key press and modify which key is pressed on a Windows Forms .NET application. -ms.date: 04/02/2025 +ms.date: 07/02/2026 ms.service: dotnet-desktop ms.update-cycle: 365-days dev_langs: @@ -19,14 +19,14 @@ Windows Forms can consume and modify keyboard input. Consuming a key refers to h ## Consume a key -In a event handler, set the property of the class to `true`. +In a event handler, set the property of the class to `true`. -or- -In a event handler, set the property of the class to `true`. +In a event handler, set the property of the class to `true`. > [!NOTE] -> Setting the property in the event handler doesn't prevent the and events from being raised for the current keystroke. Use the property for this purpose. +> Setting the property in the event handler doesn't prevent the and events from being raised for the current keystroke. Use the property for this purpose. The following example handles the event to consume the `A` and `a` character keys. Those keys can't be typed into the text box: @@ -35,7 +35,7 @@ The following example handles the e ## Modify a standard character key -In a event handler, set the property of the class to the value of the new character key. +In a event handler, set the property of the class to the value of the new character key. The following example handles the event to change any `A` and `a` character keys to `!`: @@ -44,9 +44,9 @@ The following example handles the e ## Modify a non-character key -You can only modify non-character key presses by inheriting from the control and overriding the method. As the input is sent to the control, it's processed before the control raises events. You can intercept these messages to modify or block them. +You can only modify non-character key presses by inheriting from the control and overriding the method. As the input is sent to the control, it's processed before the control raises events. You can intercept these messages to modify or block them. -The following code example demonstrates how to use the property of the `m` parameter to change the key pressed. This code detects a key from F1 through F10 and translates the key into a numeric key ranging from 0 through 9 (where F10 maps to 0). +The following code example demonstrates how to use the property of the `m` parameter to change the key pressed. This code detects a key from F1 through F10 and translates the key into a numeric key ranging from 0 through 9 (where F10 maps to 0). :::code language="csharp" source="snippets/how-to-change-key-press/csharp/NewTextBox.cs" id="PreProcessMessage"::: :::code language="vb" source="snippets/how-to-change-key-press/vb/NewTextBox.vb" id="PreProcessMessage"::: diff --git a/dotnet-desktop-guide/winforms/input-keyboard/how-to-check-modifier-key.md b/dotnet-desktop-guide/winforms/input-keyboard/how-to-check-modifier-key.md index 94cf921adf..30f5e27e33 100644 --- a/dotnet-desktop-guide/winforms/input-keyboard/how-to-check-modifier-key.md +++ b/dotnet-desktop-guide/winforms/input-keyboard/how-to-check-modifier-key.md @@ -1,7 +1,7 @@ --- title: "Check which modifier key is pressed" description: Learn how to detect when the SHIFT, ALT, or CTRL keys are pressed in Windows Forms for .NET. -ms.date: 04/02/2025 +ms.date: 07/02/2026 ms.service: dotnet-desktop ms.update-cycle: 365-days dev_langs: @@ -32,7 +32,7 @@ As the user types keys into your application, you can monitor for pressed modifi If you handle the event, the property received by the event handler specifies which modifier keys are pressed. Also, the property specifies the character that was pressed along with any modifier keys combined with a bitwise OR. -If you're handling the event or a mouse event, the event handler doesn't receive this information. Use the property of the class to detect a key modifier. In either case, you must perform a bitwise AND of the appropriate value and the value you're testing. The enumeration offers variations of each modifier key, so it's important that you do the bitwise AND check with the correct value. +If you're handling the event or a mouse event, the event handler doesn't receive this information. Use the property of the class to detect a key modifier. In either case, you must perform a bitwise AND of the appropriate value and the value you're testing. The enumeration offers variations of each modifier key, so it's important that you do the bitwise AND check with the correct value. For example, the following key values represent the SHIFT key: @@ -45,7 +45,7 @@ The correct value to test SHIFT as a modifier key is property and the enumeration value with a bitwise AND operator. +Detect if a modifier key is pressed by comparing the property and the enumeration value with a bitwise AND operator. The following code example shows how to determine whether the SHIFT key is pressed within the and event handlers. diff --git a/dotnet-desktop-guide/winforms/input-keyboard/how-to-handle-forms.md b/dotnet-desktop-guide/winforms/input-keyboard/how-to-handle-forms.md index c773f03cbc..d2f3f9dde6 100644 --- a/dotnet-desktop-guide/winforms/input-keyboard/how-to-handle-forms.md +++ b/dotnet-desktop-guide/winforms/input-keyboard/how-to-handle-forms.md @@ -1,7 +1,7 @@ --- title: "Handle keyboard input at the Form level" description: Learn how to handle keyboard input for your Windows Forms at the form level, before messages reach a control. -ms.date: 04/02/2025 +ms.date: 07/01/2026 ms.service: dotnet-desktop ms.update-cycle: 365-days dev_langs: @@ -19,11 +19,41 @@ Windows Forms provides the ability to handle keyboard messages at the form level ## Handle a keyboard message -Handle the or event of the active form and set the property of the form to `true`. This property causes the keyboard to be received by the form before they reach any controls on the form. The following code example handles the event by detecting all of the number keys and consuming 1, 4, and 7. +Handle the or event of the active form and set the property of the form to `true`. This property causes keyboard input to reach the form before it reaches any controls on the form. The following code example handles the event by detecting all of the number keys and consuming 1, 4, and 7. :::code language="csharp" source="snippets/how-to-handle-forms/csharp/Form1.cs" id="HandleKey"::: :::code language="vb" source="snippets/how-to-handle-forms/vb/Form1.vb" id="HandleKey"::: +## When `KeyPreview` is not enough + +Setting `Form.KeyPreview = true` doesn't guarantee that every key reaches form-level event handlers. Certain keys go through preprocessing before standard form events run. Understanding these exceptions is important for handling command keys, dialog keys, and control-specific input correctly. + +### Command and dialog key preprocessing + +Before form-level keyboard events fire, Windows preprocesses certain keys through these methods (in order): + +1. : Intercepts command keys such as menu shortcuts and accelerators. If this method returns `true`, the key is consumed and no event fires. +1. : Determines whether a key should raise a event or go to . +1. : Handles navigation keys (Escape, Tab, Return, and arrow keys). If processed, no event fires. + +If a focused control consumes a key during preprocessing, the form never receives it, regardless of `KeyPreview`. + +### Special cases that bypass form-level handlers + +- **Enter and Escape**: These keys might be handled by and before reaching form events. +- **Tab**: Often consumed by control focus management and won't reach form handlers. +- **Menu shortcuts**: Alt key combinations are handled by menu preprocessing. + +### Intercept command keys at the form level + +To handle command keys (including menu shortcuts and dialog keys) at the form level, override on your form. This runs during preprocessing, before standard form events. + +:::code language="csharp" source="snippets/how-to-handle-forms/csharp/Form1.cs" id="ProcessCmdKey"::: + +:::code language="vb" source="snippets/how-to-handle-forms/vb/Form1.vb" id="ProcessCmdKey"::: + +For keys that should raise standard events in a specific control, use with set to `true` on that control. + ## See also - [Overview of using the keyboard](overview.md) diff --git a/dotnet-desktop-guide/winforms/input-keyboard/how-to-simulate-events.md b/dotnet-desktop-guide/winforms/input-keyboard/how-to-simulate-events.md index d24af4ab81..a891766405 100644 --- a/dotnet-desktop-guide/winforms/input-keyboard/how-to-simulate-events.md +++ b/dotnet-desktop-guide/winforms/input-keyboard/how-to-simulate-events.md @@ -1,7 +1,7 @@ --- title: "Simulate keyboard events" description: Learn how to simulate keyboard events in Windows Forms for .NET. -ms.date: 04/02/2025 +ms.date: 07/02/2026 ms.service: dotnet-desktop ms.update-cycle: 365-days dev_langs: @@ -18,12 +18,12 @@ Windows Forms provides a few options for programmatically simulating keyboard in ## Use SendKeys -Windows Forms provides the class for sending keystrokes to the active application. There are two methods to send keystrokes to an application: and . The difference between the two methods is that `SendWait` blocks the current thread when the keystroke is sent, waiting for a response, while `Send` doesn't. For more information about `SendWait`, see [To send a keystroke to a different application](#to-send-a-keystroke-to-a-different-application). +Windows Forms provides the class for sending keystrokes to the active application. There are two methods to send keystrokes to an application: and . The difference between the two methods is that `SendWait` blocks the current thread when the keystroke is sent, waiting for a response, while `Send` doesn't. For more information about `SendWait`, see [To send a keystroke to a different application](#to-send-a-keystroke-to-a-different-application). > [!CAUTION] -> If your application is intended for international use with various keyboards, the use of could yield unpredictable results and should be avoided. +> If your application is intended for international use with various keyboards, the use of could yield unpredictable results and should be avoided. -Behind the scenes, `SendKeys` uses an older Windows implementation for sending input, which might fail on Windows where it's expected that the application isn't running with administrative rights. If the older implementation fails, the code automatically tries the newer Windows implementation for sending input. Additionally, when the class uses the new implementation, the method no longer blocks the current thread when sending keystrokes to another application. +Behind the scenes, `SendKeys` uses an older Windows implementation for sending input, which might fail on Windows where it's expected that the application isn't running with administrative rights. If the older implementation fails, the code automatically tries the newer Windows implementation for sending input. Additionally, when the class uses the new implementation, the method no longer blocks the current thread when sending keystrokes to another application. > [!IMPORTANT] > If your application relies on consistent behavior regardless of the operating system, you can force the class to use the new implementation by adding the following application setting to your app.config file. @@ -38,7 +38,7 @@ Behind the scenes, `SendKeys` uses an older Windows implementation for sending i ### To send a keystroke to the same application -Call the or method of the class. The specified keystrokes are received by the active control of the application. +Call the or method of the class. The specified keystrokes are received by the active control of the application. The following code example uses `Send` to simulate pressing the Alt and Down arrow keys together. These keystrokes cause the control to display its dropdown. This example assumes a with a and . @@ -47,13 +47,16 @@ The following code example uses `Send` to simulate pressing the Alt a ### To send a keystroke to a different application -The and methods send keystrokes to the active application, which is usually the application you're sending keystrokes from. To send keystrokes to another application, you first need to activate it. Because there's no managed method to activate another application, you must use native Windows methods to focus the other application. The following code example uses platform invoke to call the `FindWindow` and `SetForegroundWindow` methods to activate the Calculator application window, and then calls `Send` to issue a series of calculations to the Calculator application. +The and methods send keystrokes to the active application, which is usually the application you're sending keystrokes from. To send keystrokes to another application, you first need to activate it. Because there's no managed method to activate another application, you must use native Windows methods to focus the other application. The following code example uses platform invoke to call the `FindWindow` and `SetForegroundWindow` methods to activate the Calculator application window, and then calls `Send` to issue a series of calculations to the Calculator application. The following code example uses `Send` to simulate pressing keys into the Windows Calculator application. It first searches for an application window with title of `Calculator` and then activates it. Once activated, the keystrokes are sent to calculate 10 plus 10. :::code language="csharp" source="snippets/how-to-simulate-events/csharp/Form2.cs" id="Calculator"::: :::code language="vb" source="snippets/how-to-simulate-events/vb/Form2.vb" id="Calculator"::: +> [!CAUTION] +> Window title lookup by name is locale-sensitive and can be brittle. Application windows might have localized or renamed titles depending on the system language and user configuration. This sample demonstrates a basic approach only and isn't recommended for production scenarios that need reliability across varied environments. For robust cross-application automation, consider using more reliable methods like window class identification or handle-based lookups, or prefer using UI automation frameworks designed for this purpose. + ## Use OnEventName methods The easiest way to simulate keyboard events is to call a method on the object that raises the event. Most events have a corresponding method that invokes them, named in the pattern of `On` followed by `EventName`, such as `OnKeyPress`. This option is only possible within custom controls or forms, because these methods are protected and can't be accessed from outside the context of the control or form. diff --git a/dotnet-desktop-guide/winforms/input-keyboard/overview.md b/dotnet-desktop-guide/winforms/input-keyboard/overview.md index eb9cee4ba6..9020de3db7 100644 --- a/dotnet-desktop-guide/winforms/input-keyboard/overview.md +++ b/dotnet-desktop-guide/winforms/input-keyboard/overview.md @@ -1,7 +1,7 @@ --- title: "Overview of keyboard input" description: Learn about how keyboard input works in Windows Forms for .NET. Keyboard events are raised by forms and controls and represent keys that are down, pressed, or up. -ms.date: 04/02/2025 +ms.date: 07/01/2026 ms.service: dotnet-desktop ms.update-cycle: 365-days ms.topic: overview @@ -27,11 +27,11 @@ Forms and controls have access to the | Method | Notes | |------------|-----------| -| | This method intercepts queued (also known as posted) Windows messages at the application level.| -| | This method intercepts Windows messages at the form and control level before they have been processed.| -| | This method processes Windows messages at the form and control level.| -| | This method performs the default processing of Windows messages at the form and control level. This provides the minimal functionality of a window.| -| | This method intercepts messages at the form and control level, after they have been processed. The style bit must be set for this method to be called.| +| | This method intercepts queued (also known as posted) Windows messages at the application level.| +| | This method intercepts Windows messages at the form and control level before they have been processed.| +| | This method processes Windows messages at the form and control level.| +| | This method performs the default processing of Windows messages at the form and control level. This provides the minimal functionality of a window.| +| | This method intercepts messages at the form and control level, after they have been processed. The style bit must be set for this method to be called.| Keyboard and mouse messages are processed by an extra set of overridable methods that are specific to those types of messages. For more information, see the [Preprocessing keys](#preprocessing-keys) section. @@ -49,32 +49,44 @@ As listed previously, there are three keyboard related events that can occur on ## Preprocessing keys -Like other messages, keyboard messages are processed in the method of a form or control. However, before keyboard messages are processed, the method calls one or more methods that can be overridden to handle special character keys and physical keys. You can override these methods to detect and filter certain keys before the control processes the messages. The following table shows the action that is being performed and the related method that occurs, in the order that the method occurs. +Like other messages, keyboard messages are processed in the method of a form or control. However, before keyboard messages are processed, the method calls one or more methods that can be overridden to handle special character keys and physical keys. You can override these methods to detect and filter certain keys before the control processes the messages. The following table shows the action that is being performed and the related method that occurs, in the order that the method occurs. + +## Quick decision guide for keyboard interception + +Choose the right interception method based on what you're trying to handle: + +| What you need | Use this approach | +|---|---| +| Filter character input (for example, numbers only, no spaces) | Handle event or override | +| Detect physical keys (for example, Shift, Alt, specific key presses) | Handle or events | +| Handle Enter or Tab within a control when normally used for navigation | Handle event and set to `true`, or override | +| Intercept menu shortcuts or command keys (for example, Ctrl+S) at the form level | Override on the form | +| Handle application-wide shortcuts before controls get them | Implement and use | ### Preprocessing for a KeyDown event |Action|Related method|Notes| |------------|--------------------|-----------| -|Check for a command key such as an accelerator or menu shortcut.||This method processes a command key, which takes precedence over regular keys. If this method returns `true`, the key message isn't dispatched and a key event doesn't occur. If it returns `false`, is called`.`| -|Check for a special key that requires preprocessing or a normal character key that should raise a event and be dispatched to a control.||If the method returns `true`, it means the control is a regular character and a event is raised. If `false`, is called. **Note:** To ensure a control gets a key or combination of keys, you can handle the event and set of the to `true` for the key or keys you want.| -|Check for a navigation key (ESC, TAB, Return, or arrow keys).||This method processes a physical key that employs special functionality within the control, such as switching focus between the control and its parent. If the immediate control doesn't handle the key, the is called on the parent control, and so on, to the topmost control in the hierarchy. If this method returns `true`, preprocessing is complete and a key event isn't generated. If it returns `false`, a event occurs.| +|Check for a command key such as an accelerator or menu shortcut.||This method processes a command key, which takes precedence over regular keys. If this method returns `true`, the key message isn't dispatched and a key event doesn't occur. If it returns `false`, is called.| +|Check for a special key that requires preprocessing or a normal character key that should raise a event and be dispatched to a control.||If the method returns `true`, it means the control is a regular character and a event is raised. If `false`, is called. **Note:** To ensure a control gets a key or combination of keys, you can handle the event and set of the to `true` for the key or keys you want.| +|Check for a navigation key (ESC, TAB, Return, or arrow keys).||This method processes a physical key that employs special functionality within the control, such as switching focus between the control and its parent. If the immediate control doesn't handle the key, the is called on the parent control, and so on, to the topmost control in the hierarchy. If this method returns `true`, preprocessing is complete and a key event isn't generated. If it returns `false`, a event occurs.| ### Preprocessing for a KeyPress event |Action|Related method|Notes| |------------|--------------------|-----------| -|Check to see the key is a normal character that should be processed by the control||If the character is a normal character, this method returns `true`, the event is raised and no further preprocessing occurs. Otherwise is called.| -|Check to see if the character is a mnemonic (such as &OK on a button)||This method, similar to , is called up the control hierarchy. If the control is a container control, it checks for mnemonics by calling on itself and its child controls. If returns `true`, a event doesn't occur.| +|Check to see the key is a normal character that should be processed by the control||If the character is a normal character, this method returns `true`, the event is raised and no further preprocessing occurs. Otherwise is called.| +|Check to see if the character is a mnemonic (such as &OK on a button)||This method, similar to , is called up the control hierarchy. If the control is a container control, it checks for mnemonics by calling on itself and its child controls. If returns `true`, a event doesn't occur.| ## Processing keyboard messages -After keyboard messages reach the method of a form or control, they're processed by a set of methods that can be overridden. Each of these methods returns a value specifying whether the keyboard message has been processed and consumed by the control. If one of the methods returns `true`, then the message is considered handled, and it isn't passed to the control's base or parent for further processing. Otherwise, the message stays in the message queue and might be processed in another method in the control's base or parent. The following table presents the methods that process keyboard messages. +After keyboard messages reach the method of a form or control, they're processed by a set of methods that can be overridden. Each of these methods returns a value specifying whether the keyboard message has been processed and consumed by the control. If one of the methods returns `true`, then the message is considered handled, and it isn't passed to the control's base or parent for further processing. Otherwise, the message stays in the message queue and might be processed in another method in the control's base or parent. The following table presents the methods that process keyboard messages. |Method|Notes| |------------|-----------| -||This method processes all keyboard messages that are received by the method of the control.| -||This method sends the keyboard message to the control's parent. If returns `true`, no key event is generated, otherwise is called.| -||This method raises the , , and events, as appropriate.| +||This method processes all keyboard messages that are received by the method of the control.| +||This method sends the keyboard message to the control's parent. If returns `true`, no key event is generated, otherwise is called.| +||This method raises the , , and events, as appropriate.| ## Overriding keyboard methods @@ -82,17 +94,21 @@ There are many methods available for overriding when a keyboard message is prepr |Task|Method| |----------|------------| -|Intercept a navigation key and raise a event. For example, you want Tab and Enter to be handled in a text box.|Override . Alternatively, you can handle the event and set of the to `true` for the key or keys you want.| -|Perform special input or navigation handling on a control. For example, you want the use of arrow keys in your list control to change the selected item.|Override | -|Intercept a navigation key and raise a event. For example in a spin-box control you want multiple arrow key presses to accelerate progression through the items.|Override .| -|Perform special input or navigation handling during a event. For example, in a list control holding down the R key skips between items that begin with the letter **r**.|Override | -|Perform custom mnemonic handling; for example, you want to handle mnemonics on owner-drawn buttons contained in a toolbar.|Override .| +|Intercept a navigation key and raise a event. For example, you want Tab and Enter to be handled in a text box.|Override . Alternatively, you can handle the event and set of the to `true` for the key or keys you want.| +|Perform special input or navigation handling on a control. For example, you want the use of arrow keys in your list control to change the selected item.|Override | +|Intercept a navigation key and raise a event. For example in a spin-box control you want multiple arrow key presses to accelerate progression through the items.|Override .| +|Perform special input or navigation handling during a event. For example, in a list control holding down the R key skips between items that begin with the letter **r**.|Override | +|Perform custom mnemonic handling; for example, you want to handle mnemonics on owner-drawn buttons contained in a toolbar.|Override .| + +## Form-level keyboard input limitations + +When handling keyboard input at the form level, be aware of preprocessing exceptions. Not all keys reach form-level handlers when `KeyPreview` is set to `true`. Command keys, dialog keys, and keys consumed by focused controls might bypass form event handlers entirely. For details on these exceptions and how to intercept keys at the preprocessing stage, see [When `KeyPreview` is not enough](how-to-handle-forms.md#when-keypreview-is-not-enough). ## See also - -- -- +- +- - [Using keyboard events](events.md) - [How to modify keyboard key events](how-to-change-key-press.md) - [How to Check for modifier key presses](how-to-check-modifier-key.md) diff --git a/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-handle-forms/csharp/Form1.cs b/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-handle-forms/csharp/Form1.cs index 7081ec4908..1f861b1704 100644 --- a/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-handle-forms/csharp/Form1.cs +++ b/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-handle-forms/csharp/Form1.cs @@ -30,19 +30,19 @@ private void textBox1_KeyDown(object sender, KeyEventArgs e) } // - // Detect all numeric characters at the form level and consume 1,4, and 7. + // Detect all numeric characters at the form level and consume 1, 4, and 7. // 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) + if (char.IsDigit(e.KeyChar)) { MessageBox.Show($"Form.KeyPress: '{e.KeyChar}' pressed."); switch (e.KeyChar) { - case (char)49: - case (char)52: - case (char)55: + case '1': + case '4': + case '7': MessageBox.Show($"Form.KeyPress: '{e.KeyChar}' consumed."); e.Handled = true; break; @@ -50,5 +50,20 @@ void Form1_KeyPress(object sender, KeyPressEventArgs e) } } // + + // + protected override bool ProcessCmdKey(ref Message msg, Keys keyData) + { + // Intercept Ctrl+A for custom handling + if (keyData == (Keys.Control | Keys.A)) + { + MessageBox.Show("Ctrl+A intercepted at form level"); + return true; // Mark as handled + } + + // Pass other keys to the base handler + return base.ProcessCmdKey(ref msg, keyData); + } + // } } diff --git a/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-handle-forms/csharp/project.csproj b/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-handle-forms/csharp/project.csproj index 8cd5cd430f..3b9228e2ae 100644 --- a/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-handle-forms/csharp/project.csproj +++ b/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-handle-forms/csharp/project.csproj @@ -1,7 +1,7 @@  WinExe - net9.0-windows + net10.0-windows true diff --git a/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-handle-forms/vb/Form1.vb b/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-handle-forms/vb/Form1.vb index 9e7bfa64f3..2dd4815603 100644 --- a/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-handle-forms/vb/Form1.vb +++ b/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-handle-forms/vb/Form1.vb @@ -12,14 +12,14 @@ Partial Public Class Form1 End Sub ' - ' Detect all numeric characters at the form level and consume 1,4, and 7. + ' Detect all numeric characters at the form level and consume 1, 4, and 7. ' Form.KeyPreview must be set to true for this event handler to be called. Private Sub Form1_KeyPress(sender As Object, e As KeyPressEventArgs) - If e.KeyChar >= Chr(48) And e.KeyChar <= Chr(57) Then + If Char.IsDigit(e.KeyChar) Then MessageBox.Show($"Form.KeyPress: '{e.KeyChar}' pressed.") Select Case e.KeyChar - Case Chr(49), Chr(52), Chr(55) + Case "1"c, "4"c, "7"c MessageBox.Show($"Form.KeyPress: '{e.KeyChar}' consumed.") e.Handled = True End Select @@ -28,4 +28,17 @@ Partial Public Class Form1 End Sub ' + ' + Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean + ' Intercept Ctrl+A for custom handling + If keyData = (Keys.Control Or Keys.A) Then + MessageBox.Show("Ctrl+A intercepted at form level") + Return True ' Mark as handled + End If + + ' Pass other keys to the base handler + Return MyBase.ProcessCmdKey(msg, keyData) + End Function + ' + End Class \ No newline at end of file diff --git a/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-handle-forms/vb/projectvb.vbproj b/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-handle-forms/vb/projectvb.vbproj index acb9ec53b7..9fa10bcef5 100644 --- a/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-handle-forms/vb/projectvb.vbproj +++ b/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-handle-forms/vb/projectvb.vbproj @@ -1,7 +1,7 @@  WinExe - net9.0-windows + net10.0-windows true Sub Main My Project\app.manifest diff --git a/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-simulate-events/csharp/Form1.cs b/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-simulate-events/csharp/Form1.cs index ad6de45e8d..b523ef3766 100644 --- a/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-simulate-events/csharp/Form1.cs +++ b/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-simulate-events/csharp/Form1.cs @@ -21,7 +21,7 @@ public Form1() private void button1_Click(object sender, EventArgs e) { comboBox1.Focus(); - SendKeys.Send("%+{DOWN}"); + SendKeys.Send("%{DOWN}"); } // diff --git a/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-simulate-events/csharp/project.csproj b/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-simulate-events/csharp/project.csproj index 47c718fd38..480ddb3c0d 100644 --- a/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-simulate-events/csharp/project.csproj +++ b/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-simulate-events/csharp/project.csproj @@ -1,7 +1,7 @@  WinExe - net9.0-windows + net10.0-windows true diff --git a/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-simulate-events/vb/Form1.vb b/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-simulate-events/vb/Form1.vb index d13c81b62f..56959fc570 100644 --- a/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-simulate-events/vb/Form1.vb +++ b/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-simulate-events/vb/Form1.vb @@ -13,7 +13,7 @@ Partial Public Class Form1 ' Private Sub Button1_Click(sender As Object, e As EventArgs) ComboBox1.Focus() - SendKeys.Send("%+{DOWN}") + SendKeys.Send("%{DOWN}") End Sub ' End Class \ No newline at end of file diff --git a/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-simulate-events/vb/projectvb.vbproj b/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-simulate-events/vb/projectvb.vbproj index cd855c6111..6b769e67d9 100644 --- a/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-simulate-events/vb/projectvb.vbproj +++ b/dotnet-desktop-guide/winforms/input-keyboard/snippets/how-to-simulate-events/vb/projectvb.vbproj @@ -1,7 +1,7 @@  WinExe - net9.0-windows + net10.0-windows true Sub Main diff --git a/dotnet-desktop-guide/winforms/input-keyboard/validation.md b/dotnet-desktop-guide/winforms/input-keyboard/validation.md index 8901c717c6..1c408c047b 100644 --- a/dotnet-desktop-guide/winforms/input-keyboard/validation.md +++ b/dotnet-desktop-guide/winforms/input-keyboard/validation.md @@ -1,7 +1,7 @@ --- title: "User input validation" description: Learn about several ways that you can use Windows Forms to validate user input in your applications. -ms.date: 04/02/2025 +ms.date: 07/02/2026 ms.service: dotnet-desktop ms.update-cycle: 365-days ms.topic: overview @@ -34,9 +34,9 @@ If you want full programmatic control over validation, or need complex validatio - If the postal code must be a valid United States Zip code, you could call a Zip code Web service to validate the data entered by the user. -The event is supplied an object of type . If you determine that the control's data isn't valid, cancel the event by setting this object's property to `true`. If you don't set the property, Windows Forms assumes that validation succeeded for that control and raises the event. +The event is supplied an object of type . If you determine that the control's data isn't valid, cancel the event by setting this object's property to `true`. If you don't set the property, Windows Forms assumes that validation succeeded for that control and raises the event. -For a code example that validates an email address in a , see the event reference. +For a code example that validates an email address in a , see the event reference. ### Event-driven validation data-bound controls @@ -55,21 +55,21 @@ So when does a control's data get validated? This is up to you, the developer. Y The implicit validation approach validates data as the user enters it. Validate the data by reading the keys as they're pressed, or more commonly whenever the user takes the input focus away from the control. This approach is useful when you want to give the user immediate feedback about the data as they're working. -If you want to use implicit validation for a control, you must set that control's property to or . If you cancel the event, the behavior of the control will be determined by what value you assigned to . If you assigned , canceling the event prevents the event from occurring. Input focus remains on the current control until the user changes the data to a valid format. If you assigned , the event won't occur when you cancel the event, but focus will still change to the next control. +If you want to use implicit validation for a control, you must set that control's property to or . If you cancel the event, the behavior of the control will be determined by what value you assigned to . If you assigned , canceling the event prevents the event from occurring. Input focus remains on the current control until the user changes the data to a valid format. If you assigned , the event won't occur when you cancel the event, but focus will still change to the next control. -Assigning to the property prevents implicit validation altogether. To validate your controls, use explicit validation. +Assigning to the property prevents implicit validation altogether. To validate your controls, use explicit validation. ### Explicit validation The explicit validation approach validates data at one time. You can validate the data in response to a user action, such as clicking a **Save** button or a **Next** link. When the user action occurs, you can trigger explicit validation in one of the following ways: -- Call to validate the last control to have lost focus. -- Call to validate all child controls in a form or container control. +- Call to validate the last control to have lost focus. +- Call to validate all child controls in a form or container control. - Call a custom method to validate the data in the controls manually. ### Default implicit validation behavior for controls -Different Windows Forms controls have different defaults for their property. The following table shows the most common controls and their defaults. +Different Windows Forms controls have different defaults for their property. The following table shows the most common controls and their defaults. | Control | Default Validation Behavior | |------------------------------------------------|-----------------------------------------------------------------| @@ -86,9 +86,9 @@ When a control maintains focus because the data it contains is invalid, it's imp - By clicking the **Close** button. - By selecting the **System** > **Close** menu. -- By calling the method programmatically. +- By calling the method programmatically. -However, in some cases, you might want to let the user close the form regardless of whether the values in the controls are valid. You can override validation and close a form that still contains invalid data by creating a handler for the form's event. In the event, set the property to `false`. This forces the form to close. For more information and an example, see . +However, in some cases, you might want to let the user close the form regardless of whether the values in the controls are valid. You can override validation and close a form that still contains invalid data by creating a handler for the form's event. In the event, set the property to `false`. This forces the form to close. For more information and an example, see . > [!NOTE] > If you force the form to close in this manner, unsaved data is lost. In addition, modal forms don't validate the contents of controls when they're closed. You can still use control validation to lock focus to a control, but you don't have to be concerned about the behavior associated with closing the form.