I have complex UserControl (grid, edit controls for grid, etc...) and I want handle CTRL+C keyboard shortcut, however I don't want disable a native functions by edit controls (textboxes, comboboxes, etc...). If the CTRL+C is not handled by other inner controls I want handle it by myself (copy whole row(s) from grid, etc...).
I tried override WndProc method in UserControl and check for WM_COPY and WM_COPYDATA, but it doesn't work. It works o开发者_如何学运维nly on final target control (TextBox for example).
You can do this by overriding ProcessCmdKey(). Check if a text box has the focus. For example:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if (keyData == (Keys.Control | Keys.C)) {
var box = this.ActiveControl as TextBoxBase;
if (box == null) {
// Do your stuff
MessageBox.Show("Copy!");
return true;
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
What you are looking for is a way to bubble events raised by a child control up to its container so that you can handle those events at the User Control's level.
The automatic propagation of events across the control hierarchy is built into WPF and is called Routed Events. However this functionality is not available out of the box in Windows Forms, so you will have to implement your own solution.
Have a look at this SO question to get some inspiration.
Related resources:
- How to route events in a Windows Forms application
I didn't try it out and i think it heavy depends on all the child controls, which are within your UserControl. But normally a keystroke is given to the actual control that has the focus. If it doesn't handle that keystroke (setting e.Handled = true
), it would be bubble up to its parent and if that doesn't handle it, it would go further till it reaches the form and finally the limbus.
So if your child controls are properly written and they can't handle the given keystroke (e.g. Control + C) it should be easy to add a handler into your UserControl to the KeyDown
event and do whatever you like.
Update
After reading your comments, i still think that the way shown by Enrico and me should be the correct one. So i think the problem is that if one of your 3rd party controls has the focus it is not able to handle the copy shortcut, but it sets the e.Handled = true
leading to no further informations of the parent controls about the shortcut.
So at first you should contact your control vendor and send him a bug report about this wrong behaviour.
Alternative there exists another hacky way:
In your form you can set the KeyPreview
to true and intercept the incoming key. Now you could check if within the ActiveControl
is something that handles the shortcut correctly (maybe a check against a Dictionary<Type, bool>
or a HashSet<Type> lackingControls
) and just leave the function or do whatever you want and setting the e.Handled = true
by yourself.
Update 2
A little snippet to illustrate what i meant:
this.KeyPreview = true;
HashSet<Type> scrappyControls = new HashSet<Type>();
//ToDo: Add all controls that say it handles Ctrl-C
// but doesn't it the right way.
scrappyControls.Add(typeof(TextBox));
this.KeyDown += (sender, e) =>
{
if (e.KeyData == (Keys.Control | Keys.C))
{
if (scrappyControls.Contains(this.ActiveControl.GetType()))
{
//ToDo: Do copy to clipboard on yourself
e.Handled = true;
}
}
};
The drawback of this functionality is, that it must be placed into your form, not into your self-written UserControl. But that way you will be informed, when a TextBox has the focus and Control + C is pressed within.
精彩评论