Capturing KeyDown events in UserControl

I have a user control with several child elements. I need the user interface to respond to keystrokes, so I decided to put the processing code in the MainControl_KeyDown event. However, when I press a key in my application, this event does not fire.

I found a solution through a search engine that relies on the use of the Windows API, which I would like to avoid, since this seems like unnecessary criticism for what should be a function that is properly supported by the .NET platform.

+6
winforms
source share
6 answers

You can add a KeyDown event handler for each child control in your user control and fire each KeyDown event of your user control as follows:

private void textBox1_KeyDown(object sender, KeyEventArgs e) { this.OnKeyDown(e); } 
+7
source share

I know that this branch is a bit outdated, but I had a similar problem and it was handled differently:
In the main window, I changed the KeyPreview attribute to true. I registered the main window's KeyDown event handler in my user control.

 this.Parent.KeyDown += new KeyEventHandler(MyControl_KeyDown); 

This does not allow me to redirect the KeyDown event of each child control to my user control.
Of course, it is important to remove the event handler when unloading the user control.

I hope this helps people who are facing a similar problem now.

+9
source share

You can add the following method to your usercontrol :

 protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { if ((keyData == Keys.Right) || (keyData == Keys.Left) || (keyData == Keys.Up) || (keyData == Keys.Down)) { //Do custom stuff //true if key was processed by control, false otherwise return true; } else { return base.ProcessCmdKey(ref msg, keyData); } } 
+6
source share

perhaps you should handle all the events locally and then trigger dummy events to communicate with the main control?

or maybe it could be a focus problem; if there are many child controls, and only one of them is focused, the others will not respond to the keystroke.

perhaps you can post some code snippets here.

+1
source share

Here is an example that a loop throws each control on a form to attach a KeyDown event. This is similar to the previous answer in this post, but handle more cases:

 using Microsoft.VisualBasic; using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics; public class UserControlKeyboardProcessor { private void Control_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) { base.OnKeyDown(e); } private void UserControlKeyboardProcessor_Disposed(object sender, System.EventArgs e) { foreach (System.Windows.Forms.Control control in this.GetAllControls(this)) { control.KeyDown -= Control_KeyDown; } } private void UserControlKeyboardProcessor_Load(object sender, System.EventArgs e) { foreach (System.Windows.Forms.Control control in this.GetAllControls(this)) { control.KeyDown += Control_KeyDown; } } public Generic.List<System.Windows.Forms.Control> GetAllControls(System.Windows.Forms.Control control) { Generic.List<System.Windows.Forms.Control> controls = new Generic.List<System.Windows.Forms.Control>(); foreach (System.Windows.Forms.Control subControl in control.Controls) { controls.Add(subControl); controls.AddRange(this.GetAllControls(subControl)); } return controls; } public UserControlKeyboardProcessor() { Load += UserControlKeyboardProcessor_Load; Disposed += UserControlKeyboardProcessor_Disposed; } } 
+1
source share

I have a trick.

UcBase inherits from UesrControl

UcSub1 and UcSub2 inherit from UcBase. UcSuperClass also inherits from UcBase.

UcSub1, UcSub2 is used in UcSuperClass.

I am madly UcSub1 and UcSub2 are calling ProcessCmdKey normally.

my codes were

 public class UcBase : UserControl { public delegate bool ProcessCmdKeyHandler(Keys keyData); public ProcessCmdKeyHandler KeyHandler; protected override void OnLoad(EventArgs e) { base.OnLoad(e); KeyHandler += ProcessKey; if (Parent != null) { var parent = GetParentControl<UcBase>(Parent); if (parent != null) { parent.KeyHandler += ProcessKey; } } } protected virtual bool ProcessKey(Keys keyData) { return false; } protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { const int WM_KEYDOWN = 0x100; const int WM_SYSKEYDOWN = 0x104; if (KeyHandler != null && (msg.Msg == WM_KEYDOWN) || (msg.Msg == WM_SYSKEYDOWN)) { if (KeyHandler(keyData) == true) { return true; } } return base.ProcessCmdKey(ref msg, keyData); } private T GetParentControl<T>(Control control) where T : Control { T parentControl = default(T); var queue = new Queue<Control>(); var targetControlType = typeof(T); queue.Enqueue(control.Parent); while (queue.Count > 0) { var parent = queue.Dequeue(); if (parent != null) { if (parent.GetType().BaseType == targetControlType) { parentControl = (T)parent; break; } else { queue.Enqueue(parent.Parent); } } else { break; } } return parentControl; } } public class UcSub1 : UcBase { protected override bool ProcessKey(Keys keyData) { // if you process do something, and return true then UcBase.ProcessCmdKey pass by. return false; } } public class UcSub2 : UcBase { protected override bool ProcessKey(Keys keyData) { // if you process do something, and return true then UcBase.ProcessCmdKey pass by. return false; } } public class UcSuperClass : UcBase { private UcSub1 _ucSub1; private UcSub2 _ucSub2; public UcSuperClass() { _ucSub1 = new UcSub1(); _ucSub2 = new UcSub2(); } protected override bool ProcessKey(Keys keyData) { // if you process do something, and return true then UcBase.ProcessCmdKey pass by. return false; } } 
0
source share

All Articles