Introduction
Ever have the problem that your controls, like a TextBox
, ComboBox
or DataGridView
for example, don't seem to be receiving any keyboard commands like Ctrl+A, Ctrl+C or Ctrl+V? It happens to me too.
I was working on an MDI program containing several childforms with multiple tab or splitter panels to hold forms controls. During the initial phase, it didn't really bother me that much. First make the app work, then make it user friendly. But after some time, I had to figure out a solution.
Background
After some testing, I discovered what was happening. All the keystrokes were getting captured by the MdiForm
owning all other childforms and their controls. Fine, so I take a look at the sender object. It’s the MdiForm
! Getting the control I was actually using was a pain, but I figured it out.
The first thing I tried was looping through the sender.Controls
collection and testing which had the ContainsFocus
property set to true
.
private void MdiForm_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control)
{
foreach (Control ctl in sender.Controls)
{
if (ctl.ContainsFocus)
{
}
}
}
}
All I got were ChildForms
. They were the correct Forms but not the controls I was looking for. So I figured that I would do the same thing on the ChildForm.Controls
collection.
foreach (Control ctl in sender.Controls)
{
if (ctl.ContainsFocus)
{
foreach (Control ctl2 in sender.Controls)
{
if (ctl2.ContainsFocus)
{
}
}
}
}
This time it wasn't a form, but yet again not the control I was looking for. This was just the control that holds the control, that holds the control that holds the controls I was looking for. And this was just for one child form. Most controls were 4, 5 or even more collections away.
I decided to take a more flexible approach and use a recursive function:
public static Control GetActiveControlOnSender(object sender)
{
if(sender is Control)
return GetActiveControl((Control) sender);
return null
}
internal static Control GetActiveControl(Control control)
{
if (!sender.ContainsFocus)
return null;
foreach (Control ctl in sender.Controls)
{
if (ctl.ContainsFocus)
{
if (ctl.Controls.Count == 0)
{
return ctl;
}
else
{
return GetActiveControl(ctl);
}
}
}
return control;
}
All I had to do now was call the function from the KeyDown
event and pass the sender
object. Then look at the object and decide what needs to happen.
private void MdiForm_KeyUp(object sender, KeyEventArgs e)
{
if (e.Control)
{
Control control = Common.GetActiveControlOnSender(sender)
switch (e.KeyCode)
{
case Keys.A:
if (control is TextBox)
((TextBox)control).SelectAll();
break;
case Keys.X:
if (control is TextBox)
((TextBox)control).Cut();
break;
case Keys.V:
if (control is TextBox)
((TextBox)control).Paste();
break;
case Keys.C:
if (control is TextBox)
((TextBox)control).Copy();
break;
}
}
}
This can be modified to work for any user control.
History
- 2008-11-28: First version
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.