Per user request I implemented NumericUpDown with varying Increment (0.1 on arrow press, 0.01 on SHIFT+arrow press) as suggested in this answer. It works very well when the user interacts with the mouse to press the control's arrows.
However, the keyboard input with the Up arrow does not trigger UpButton() when the SHIFT is pressed (same for the Down key and the DownButton()). Instead, the text in the control is being selected. Since the normal behavior is for both methods to be triggered when the keyboard arrows are pressed, of course I would like to keep this functionality on for the SHIFT combination as well.
So far I have tried overriding every method in the NumericUpDown which contains the "Key" word but none could help me. ProcessCmdKey can detect the key combination and disable the default selection behavior but it doesn't not lead to UpButton/DownButton being triggered either.
Any ideas?
Shift + Up/Down are text selection shortcut keystrokes for the textbox portion of the NumericUpdate. Just as they are for a regular TextBox. Disabling this feature isn't the greatest idea.
Multiple ways to do this, perhaps the easiest is to detect the keystroke in an override for the form's ProcessCmdKey() method. So they'll work on any NUD and the code changes are small. I'll post the C# version of it, creating a winforms app in C++/CLI is too much of a hassle these days:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
var ctl = this.ActiveControl as NumericUpDown;
if (ctl != null) {
if (keyData == (Keys.Up | Keys.Shift)) {
ctl.Value = Math.Min(ctl.Maximum, ctl.Value + 10 * ctl.Increment);
return true;
}
if (keyData == (Keys.Down | Keys.Shift)) {
ctl.Value = Math.Max(ctl.Minimum, ctl.Value - 10 * ctl.Increment);
return true;
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
Related
I'm trying this code in my PreviewKeyDown event to detect if hash key (#) is pressed or not but it still show number (3) in my TextBox and MessageBox:-
private void text_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.D3 && Keyboard.Modifiers == ModifierKeys.Shift)
MessageBox.Show(e.Key.ToString());
}
How can I modify or change this code to do what I need ?!
Thanks.
KeyDown captures the last key that was pressed down, which was Key.D3, hence why you see 3 in your output. This is expected behavior.
Why would you want to use e.Key.ToString() though? This would make sense if you wanted to see which key is being pressed, but you are explicitly checking for the SHIFT + 3 combo beforehand, so you already know what you're after.
// slightly modified your check
if (e.Key == Key.D3 && (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift)
{
MessageBox.Show("SHIFT+3 combo pressed");
}
Also, as #keyboardP noted in the comments, the location of the # sign on the keyboard depends on the layout of the keyboard itself (US/UK etc), or as you have it configured by your operating system. Perhaps you could add checking of the keyboard layout into the mix (might be worth having a look at the InputLanguageManager class from the System.Windows.Input namespace).
EDIT: As an alternative, why not just track whether the # character was input in the textbox, rather than checking for keyboard combos? It seems much more straightforward to me, though it depends on your requirements.
I've seen a number of answers suggesting the use of Keyboard.Modifiers to determine whether a KeyDown event is for a key that had a modifier set. Unfortunately, because Keyboard.Modifiers returns the current state of the modifiers (instead of the state of the modifier when the key was pressed), this results in a really annoying intermittent bug for quick typists.
Specifically, imagine someone presses Ctrl+A, and releases Ctrl only a few milliseconds after pressing A. Now imagine that the system was under heavy load; the key handler started executing but was preempted for 50ms. By the time the key handler is executing again, the current state of Ctrl is "released". The key handler will now think that "A" was pressed without Ctrl, and this is bad.
Similarly, if a fast typist enters A, Ctrl+End and my application uses Keyboard.Modifiers, it could instead end up observing Ctrl+A...
In WinForms, the KeyDown event tells me the state of Ctrl exactly, even if it's already released by the time the event is being handled. How can I get this same behaviour in WPF?
Edit: it's possible that Keyboard.Modifiers doesn't actually retrieve the "current" modifier keys, but instead the modifier keys as related to the key down message currently being processed. In WinAPI, this was the distinction between "async" and non-async key state functions. Unfortunately, the documentation doesn't mention what exactly "current" means. If anyone knows, please say so.
As there does not appear to be any modifier information in the event args you could keep track of the state yourself in some fields and handling both KeyUp and KeyDown to update them accordingly.
e.g.
private bool ctrl = false;
private void This_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.LeftCtrl) //or switch, also: `LeftCtrl` & `RightCtrl` are treated as separate keys
ctrl = true;
//etc..
}
private void This_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.LeftCtrl)
ctrl = false;
//etc..
}
Whether this is actually a good idea i cannot say...
If you want to handle key gestures i would suggest using dedicated methods like KeyBindings they should only fire when the gesture happened. For other input you may also want to have a look at TextInput which is more abstract and returns the text that the input is translated to.
sorry for this destructive answer but...
after a little bit of research it becomes clear to me...
the event is called "KeyDown" not "KeyCombinationDown" so it is totally independent of any Modifiers pressed BEFORE...
Actually there is a right way for achieve your goal:
Using the Commanding-Pattern.
You define a COMMAND (see google for WPF-Commanding) and add a KeyBinding to your application, where you define the key or the keys/key-combination which will fire up the command...
See the example here:
http://msdn.microsoft.com/en-us/library/system.windows.input.keybinding.aspx
IMHO, this is the only way and semantically more elegant, too.
(if this pattern will not be working for you in GENERAL, you maybe have to use native api with pinvoke).
cheers.
I want to detect when a combination like Ctrl-C is pressed in a WPF application. What I've read online says to use something like the following in the KeyDown (or KeyUp) Event:
if ((Keyboard.Modifiers == ModifierKeys.Control) && (e.Key == Key.S))
{
MessageBox.Show("Save!");
}
I'm just trying to understand how this works. As I understand it, e.Key contains the key that was pressed that triggered the event and Keyboard.Modifiers contains the information about the state of the Control key right now. Is it safe to assume that the Control key will still be down by the time the KeyDown event gets handled?
For example, I restart Firefox and it grinds away loading a bunch of tabs, and in the meantime I hit Ctrl-S in my application. There is a delay in getting to KeyDown, and the application thinks just S has been pressed.
Thanks
You could use KeyBindings instead, they define full gestures without such a separation.
I need to respond to keydown events (O, C, G keys etc., not modifier keys) while a Drag+Drop operation is in progress over my control (i.e. between DragEnter and DragLeave). However the KeyDown event is not called at this stage.
I've tried selecting my control and specifically setting focus on DragEnter, but that doesn't work.
EDIT:
Hans' answer is basically correct, except I had to use GetAsynchKeyState to get the behaviour I wanted.
The QueryContinueDrag event is raised on the drag source. Checking for the state of the keys you are interested in is going to require pinvoke, the event is only designed to help recognize the Escape key and modifier key state changes. Which is something to keep in mind, that these keys have any special action is very undiscoverable.
[DllImport("user32.dll")]
private static extern short GetKeyState(Keys key);
It returns a value < 0 when the key is down. I can't say it's guaranteed to work correctly but it looked good when I tried it.
You can also try:
Keyboard.IsKeyDown(); method to check if a specific key is pressed, i.e.:
bool isKeyPressed = Keyboard.IsKeyDown(Key.LeftAlt);
It's similar to the previous answer, but it's a native .NET method, so it doesn't require you to import any functions.
A similar question has been asked here: Handle KeyDown during a drag drop. Or keydown event not workign, but there was a suggestion to make it work like an event.
UPDATE
The first solution seems to work only in WPF. If you want to check states of modifier keys, there is, however, a method utilizing a property Form.ModifierKeys that should work correctly in WinForms. The example shows how to check if alt (left alt) and ctrl keys are both pressed:
if (Form.ModifierKeys == (Keys.Alt | Keys.Control))
{
//TODO: insert your code here
}
I am trying to capture any keystroke that happens inside my Silverlight 2 application. There are not any input fields, I'm writing a game, and need to know which of the arrow keys are being pressed. My best guesses at how to capture these through an event handler are unsuccessful. Any recommendations?
Good to see you again (virtually).
I'm assuming you already tried wiring KeyDown on the root UserControl element. Here are some tips:
The plugin needs focused before it sees key events. You'll have to force the user into clicking on the plugin to start.
Make sure you don't have another element (like the ScrollViewer) that is eating arrow keys events. If you have a ScrollViewer in play you'll only be seeing KeyUp.
No switching to full screen mode.
Must be something simple you are missing like that. Hope that helps.
Handle the KeyDown and/or the KeyUp event on your root Grid.
Silverlight 2 supports the KeyUp and KeyDown events (only, I believe - not KeyPress).
In these events, you get a KeyEventArgs object as a parameter. You can get the KeyCode or KeyData from this.
In reviewing a few different threads from different forums regarding this matter it would seem it is best to handle your keyevents on your Page (root) element, parse the key for the desired effect, and redirect your command to the particular control.
Page
this.KeyDown += (s, e) =>
{
MyControl control = (MyControl)Layoutroot.FindName("controlname");
if(control != null)
{
control.MyPublicFunction(e.Key);
}
};
MyControl
public MyPublicFunciton(Key pressedKey)
{
if(pressedKey == Key.Enter)
{
//Do something
}
}