Detecting key combinations - wpf

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.

Related

Alt-Tab issue on Windows Activation in WPF

In my app, I have a special action mapped to the tab key. The problem is that when you use the short-cut Alt-Tab to switch between different apps, my app gets a tab key (but not the Alt key) when it becomes activated, which I'd like to avoid. This happens sometimes (not all the time), especially when you switch apps very fast.
I could filter it out by checking Keyboard.IsKeyDown(Key.LeftAlt), but my app doesn't get the Alt-key in this case. Any tip?
I've had an issue where KeyUp event handler doesn't register e.Key == Key.LeftAlt. Instead I had to use e.SystemKey == Key.LeftAlt. Perhaps you are facing a similar issue (although I don't know if you use the KeyUp/KeyDown event handler)?
Another thing to try would be Keyboard.Modifiers == ModifierKeys.Alt or maybe even KeyboardDevice.Modifiers == ModifierKeys.Alt inorder to filter out Alt.

How to correctly retrieve modifier keys in a WPF KeyDown event?

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.

Handle KeyDown during a drag drop

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
}

How do I capture keystrokes in a Silverlight application?

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
}
}

WPF - How to capture when CTRL+SHIFT are pressed down?

When the user clicks left CTRL+ left SHIFT I want to make the entire application translucent (like VS2008's intellisense drop-down). If I write my code on the KeyUp event I can capture both keys being pressed, but the transparency effect should only be active while the keys are pressed. When they are release the opacity should go back to 100%. The behavior I want is actually the KeyDown event, but I can't capture both keys on KeyDown, can I?
Thanks
Use the static methods of the Keyboard class, specifically IsKeyDown() to check the state of the keys you're interested in.
On KeyDown you can use this to enable the translucency and on KeyUp you can disable the effect again. If you are at it, you could save the key's state yourself and act upon it.

Resources