Can you please tell me how to bind a keyboard key to a button C # form? The Click event is already taken. And I don't understand KeyPress how it works. I am writing a calculator.

  • one
    For a start, look here. If no one can write in detail, in the evening I will try to paint the work with the keyboard in forms. There is generally a lot of information on this topic, but you need to search in pieces. - rdorn

2 answers 2

WinForms and the keyboard are a pretty fun combination, especially when you try to get them to work in concert.

1. Events Control.Key *

Any control can respond to keystrokes and several events are defined for this: Control.KeyDown , Control.KeyPress , Control.KeyUp . It seems to be all right, we subscribe to events and get a response to the keys. But there is one catch - these events only work when the control is in focus . In addition, many controls already have standard key handlers, many react to a space like a click, and TextBox and its relatives intercept almost the entire keyboard.

2. Form also control

The Form class is also inherited from the control, and is able to receive these events. It seems to be obvious, we transfer key handling to form events and rejoice, it also seems to be always in focus. But here it is not so simple. If the child control is configured to handle the keys and is in focus (and if there are child controls on the form, then one of them is necessarily in focus), then the form simply ignores key presses.

You can recall the form property. KeyPreview , which is designed to intercept events, then the keyboard events will first be transferred to the form. It seems to be a working version, but if you don’t want the standard functionality of the controls to still work, then you will have to remember to set the KeyPressEventArgs.Handled = false; property KeyPressEventArgs.Handled = false; so that after processing the keyboard event at the form level, it was passed to the child controls. Honestly, this is not the best option, because It has its limitations and not all tasks can be solved in this way. Although he seems to be designed for this.

3. We will save the menu

The first solution to the problem regarding non-shamanism is to add MenuStrip to the menu form. The menu is made in such a way that it is possible to bind a hot key to each of its elements, and for their correct operation the menu intercepts all keyboard events and sends further only those that are not associated with pressing the specified keys and combinations. The way everyone is good, except for a couple of moments: for all the necessary keys and combinations, you need an item in the menu and you need the menu itself on the form. If the first problem can still be solved by using hidden elements (I have not personally checked it), then the second is really a problem, because Not any form of the application allows the presence of a menu on it, but adding it just for the sake of processing keys ... well, you understand me.

4. Universal solution

Do not rush to rejoice, all the previous points required only mastery of clicking the mouse in the interface of the designer, and here you will need to write code.

In the form, like any control, there is a virtual method ProcessCmdKey , which is responsible for the default handling of keyboard events, and this is what we need to redefine in our form to get the expected and correct work with the keyboard.

 protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { //ваша логика тут return base.ProcessCmdKey(ref msg, keyData); } 

Calling the base method is optional. The result of the operation of the method is responsible for the transmission of the event to the child controls; only the logic is a little bit opposite: true - the key is processed, no further processing is required; false - the event will be passed to child controls, even if you have performed some preprocessing. Thus, you get full control over the handling of keyboard events at the form or custom control level.

The advantage of this method is that you get access to the keyData parameter, which, unlike KeyPressEventArgs contains not only the displayed symbol, but all the information about the key pressed, including the scan code, the state of the modifier keys and other useful information. For exactly what event occurred, the msg parameter is answered, which contains the WinAPI system message. We are interested in the WM_KEYDOWN and WM_KEYUP related to the keyboard. The KeyPress event is actually the sequential receipt of WM_KEYDOWN and WM_KEYUP.

5. Well, and how to use it?

Yes, actually as usual. Pressing the key and clicking on the button is a user action that should cause some kind of program reaction. The reaction is described by a separate private method, and in the click handlers of the button and pressing the key we put a call to this method. This approach eliminates the need to copy code, minimizes the code of event handlers, allows you to trigger a given program response in any desired way, be it a click on any control, a checkbox or radio button, a key or a combination, a menu item or all at once. The reaction code is in one place and, if necessary, you will not have to think about changing it, where else you forgot to correct it.


If you have enough enthusiasm, I will later gather in this answer links to related questions with good answers. In the meantime, the first thing that was found on the topic without deep digging:

How to intercept keystrokes in Windows Forms (C ++)?
Handling numeric keypads

  • Is it possible to make so that protected override bool ProcessCmdKey with its switch would refer to, for example, private void keyZero_KeyPress (object sender, KeyPressEventArgs e)? - John Shepard
  • @JohnShepard is not, transfer the code from the handler to a separate method and call in the handler and switch. It will not take much time, but it will relieve a headache in the future - rdorn

If I understand the question correctly, then you can use the KeyDown . Pressing the space bar will execute the button code.

 private void button1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Space) MessageBox.Show("Hello!"); } 
  • It does not suit me. All my buttons (forms) are busy with private void keyZero_Click(object sender, EventArgs e) { textBox1.Text += (sender as Button).Text; } private void keyZero_Click(object sender, EventArgs e) { textBox1.Text += (sender as Button).Text; } That is buttons (forms) - John Shepard
  • the space button responds by default as a click when it is in focus. - rdorn