Is there a possibility to handle WinKey+ArrowKey key combination before Windows handle it for WPFWindow? With OnPreviewKeyDown(KeyEventArgs e) I can catch when WinKey and ArrowKey are pressed separately, but not WinKey+ArrowKey combination. Seems that it is handled by system and window only get resizing command. Is there any way to handle this combination before system?
To do this, you will need to use a Global Keyboard Hook. There is a good project that would get you started in the right direction here: https://www.codeproject.com/Articles/19004/A-Simple-C-Global-Low-Level-Keyboard-Hook
To reiterate Hans Passant's warning, this will catch the key combination even if your program is running in the background. If this is not what you want, then you will need to subscribe and unsubscribe to the events when your program is focused/unfocused or put additional logic in there to detect whether your program is the focused program before taking any action.
If you import the classes from the link, then you can implement them in your code like this (EDIT: this seems to work with KeyValue, but not with KeyCode):
GlobalKeyboardHook gkh = new GlobalKeyboardHook();
private bool _winKeyPressed;
public MyConstructor()
{
gkh.HookedKeys.Add(Keys.Left); //37
gkh.HookedKeys.Add(Keys.Up); //38
gkh.HookedKeys.Add(Keys.Right); //39
gkh.HookedKeys.Add(Keys.Down); //40
gkh.HookedKeys.Add(Keys.LWin); //91
gkh.HookedKeys.Add(Keys.RWin); //92
gkh.KeyDown += gkh_KeyDown;
gkh.KeyUp += gkh_KeyUp;
}
private void gkh_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyValue == 91 || e.KeyValue == 92)
{
// left or right windows key was released
_winKeyPressed = false;
}
}
void gkh_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyValue == 91 || e.KeyValue == 92)
{
// left or right windows key was pressed
_winKeyPressed = true;
}
if (e.KeyValue == 39 && _winKeyPressed == true)
{
// right key
MessageBox.Show("This works.");
}
}
Related
I have a pretty complex visual studio form where I have like 2 textboxes, and some other stuff I need for my project, but my problem is - I want to use arrow keys to do tasks (bind them like short-cuts) and I can do that only when I don't edit my textboxes or else I get stuck in them and even if I try to reset my cursor (click on the form) it stays in the textbox and I can only jump in between characters, not use my arrows like I binded them. So my two questions are -
How can I reset my cursor if I have previously selected a textbox?
How can I unbind my default arrow keys so they don't jump between characters and buttons?
Try adding a key event on the textboxes that catches the arrow key strokes and moves focus accordingly.
void inputField_KeyDown(object sender, KeyEventArgs e)
{
if ((e.KeyCode == Keys.Left) || (e.KeyCode == Keys.Right) || (e.KeyCode == Keys.Up) || (e.KeyCode == Keys.Down))
{
//nextControl.Focus();
}
}
Just be aware that this will then remove the ability to navigate between the characters in a textbox. I think that the numpad arrows might still work inside the textbox since they have a different keycodes, but I can't be sure right now.
Hi and Welcome to stackoverflow, I'm not sure i have a complete answere but I have a few thougth on the subject.
Hard to answeer without some code, to se how you turns off the curser i think?
why does it have to in the first place? seems to overcomlicate it abit ?
the way i whould go about this, it's to egnore the the muse curser all together at first, and make a on KeyDown event on the textbox that needs the to be able to shift to the next like this
private void yourControl_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.Down || e.KeyData == Keys.Up)
{
// shift to next textbox maybe, to keep thing simple ?
}
}
though this will act wierd if you use a mulitlines textbox or other control that allready have these keys bind.
you can allso add a field boolean as a switch to enable the keys, that gets set on the textsboxes activation (thats what happens then you click it to write text) and it can be reused, then it look like this
class yourProgram
{
private bool fieldIskeysMode = false;
private void yourControl_KeyDown(object sender, KeyEventArgs e)
{
if (fieldIskeysMode) // if True
{
if (e.KeyData == Keys.Down || e.KeyData == Keys.Up)
{
// shift to next textbox maybe, to keep thing simple ?
}
if (e.KeyData == Keys.Escape) fieldIskeysMode = false; // one line set to falls on esc key
}
}
private void yourControl_Activate(object sender, KeyEventArgs e)
{
if (!fieldIskeysMode) // if not true
{
fieldIskeysMode = true;
}
}
}
hope this helps.
I have an application in which I have implemented some keyboard shortcut keys for a given set of operations, some of these use ALT as a modifier e.g. ALT + 1. The functionality itself works fine however the system beeps during the key press.
I have read various posts that say I could use e.Handled in the KeyPress event however this is not helping in my scenario. The problem is easily replicated by creating a new Windows Forms application and running it without any modifications, pressing ALT + 1 for example will cause the system to beep.
I have noticed that other application such as Notepad have this behaviour too, if you launch Notepad and press ALT + J (or any other invalid menu keypress) the system will beep.
Is there any way to prevent the beep via my application or is it standard Windows behaviour?
You can Handle KeyDown Event and do something like this for Alt+1 But i suspect you might have to do this for all the invalid keys
private void keyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode >= Keys.D1 && e.Alt)
{
e.Handled = true;
e.SuppressKeyPress = true;
}
}
Can you try to use SuppressKeyPress in you KeyPress event management?
e.SuppressKeyPress = true;
I use Alt+E for editing a record under certain circumstances.
Here's what I had to do to eliminate the beep.
private void Object_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.E && e.Alt)
{
e.SuppressKeyPress = true;
}
}
private void Object_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.E && e.Alt)
{
e.SuppressKeyPress = true;
EditRecord(); // This opens a form for the editing process
}
}
Note: If you try to use EditRecord from Object_KeyDown and only SuppressKeyPress in Object_KeyUp, you will still get the beep.
Is it possible, to capture (somewhere in app.xaml.cs i guess) any key and if it pressed open window?
Thanks for help!
There is a better way. Found this on a MS forum. Works like a charm.
Put this code in Application startup:
EventManager.RegisterClassHandler(typeof(Window),
Keyboard.KeyUpEvent,new KeyEventHandler(keyUp), true);
private void keyUp(object sender, KeyEventArgs e)
{
//Your code...
}
You could use something like this gist to register a global hook. It will fire whenever the given keys are pressed while your application is running. You can use it in your App class like this:
public partial class App
{
private HotKey _hotKey;
protected override void OnActivated(EventArgs e)
{
base.OnActivated(e);
RegisterHotKeys();
}
protected override void OnExit(ExitEventArgs e)
{
base.OnExit(e);
UnregisterHotKeys();
}
private void RegisterHotKeys()
{
if (_hotKey != null) return;
_hotKey = new HotKey(ModifierKeys.Control | ModifierKeys.Shift, Key.V, Current.MainWindow);
_hotKey.HotKeyPressed += OnHotKeyPressed;
}
private void UnregisterHotKeys()
{
if (_hotKey == null) return;
_hotKey.HotKeyPressed -= OnHotKeyPressed;
_hotKey.Dispose();
}
private void OnHotKeyPressed(HotKey hotKey)
{
// Do whatever you want to do here
}
}
Yes and no.
Focus plays a role in the order for which a given key is handled. The control which captures the initial key press can opt to not pass the key along, which would prohibit you from capturing it at the top most level. In addition there are controls within the .NET framework that swallow certain keys under certain scenarios, however I am unable to recall a specific instance.
If your application is small and the depth is nothing more than a Window with buttons, this is certainly attainable and would follow the standard approach to capturing key strokes within a WPF application.
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)
myVariable = true;
if (ctrl && e.Key == Key.S)
base.OnKeyDown(e);
}
protected override void OnKeyUp(KeyEventArgs e)
{
if (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)
myVariable = false;
base.OnKeyUp(e);
}
If your application is large you can attempt a global hook as detailed here but understand that the aforementioned caveats can still exist.
I have a from that has a text box and I'm trying to determine if Ctrl-R is pressed within this text box. I can detect the keys separately using:
private void CheckKeys(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if(e.KeyChar == (char)Keys.R)
{
// ...
}
if ((Control.ModifierKeys & Keys.Control) == Keys.Control)
{
// ...
}
}
How do I determine if they pressed at the same time?
If possible, change your event to KeyDown/KeyUp, everything will be easier. (Note that this solution is not always applicable)
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyData == (Keys.Control | Keys.R))
{
}
}
See Mitch's answer on how to construct the bit flag logic correctly, as long as he undeletes it. Here's something that will work, if he doesn't decide to. You basically need to check if both conditions are true at the same time:
bool isRKeyPressed = e.KeyChar == (char)Keys.R;
bool isControlKeyPressed = (Control.ModifierKeys & Keys.Control) == Keys.Control;
if (isRKeyPressed && isControlKeyPressed)
{
// Both ...
}
else if (isRKeyPressed)
{
// R key only ...
}
else if (isControlKeyPressed)
{
// CTRL key only ...
}
else
{
// None of these...
}
Throw away any of these checks that you don't care about.
Also, you might want out check out this alternative approach:
http://www.codeguru.com/columns/experts/article.php/c4639
They override the ProcessCmdKey method on their form (possibly on individual controls?):
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.processcmdkey.aspx
Despite me working with C# (Windows Forms) for years, I'm having a brain fail moment, and can't for the life of me figure out how to catch a user typing Ctrl + C into a textbox.
My application is basically a terminal application, and I want Ctrl + C to send a (byte)3 to a serial port, rather than be the shortcut for Copy to Clipboard.
I've set the shortcuts enabled property to false on the textbox. Yet when the user hits Ctrl + C, the keypress event doesn't fire.
If I catch keydown, the event fires when the user presses Ctrl (that is, before they hit the C key).
It's probably something stupidly simple that I'm missing.
Go ahead and use the KeyDown event, but in that event check for both Ctrl and C, like so:
if (e.Control && e.KeyCode == Keys.C) {
//...
e.SuppressKeyPress = true;
}
Also, to prevent processing the keystroke by the underlying TextBox, set the SuppressKeyPress property to true as shown.
Key events occur in the following order:
KeyDown
KeyPress
KeyUp
The KeyPress event is not raised by noncharacter keys; however, the noncharacter keys do raise the KeyDown and KeyUp events.
Control is a noncharacter key.
You can check with this line of code:
if (e.KeyData == (Keys.Control | Keys.C))
I had a problem catching Ctrl + C on a TextBox by KeyDown. I only got Control key when both Control and C were pressed. The solution was using PreviewKeyDown:
private void OnLoad()
{
textBox.PreviewKeyDown += OnPreviewKeyDown;
textBox.KeyDown += OnKeyDown;
}
private void OnPreviewKeyDown( object sender, PreviewKeyDownEventArgs e)
{
if (e.Control)
{
e.IsInputKey = true;
}
}
private void OnKeyDown( object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.C) {
textBox.Copy();
}
}
D'oh! Just figured it out. Out of the three possible events, the one I haven't tried is the one I needed! The KeyUp event is the important one:
private void txtConsole_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyData == (Keys.C | Keys.Control))
{
_consolePort.Write(new byte[] { 3 }, 0, 1);
e.Handled = true;
}
}
If you want to catch such combinations of keys in KeyPress Event look at this table here:
http://www.physics.udel.edu/~watson/scen103/ascii.html
in Non-Printing Characters section you can see the Dec numbers for each combination.
For example, Dec number for Ctrl + C is 3. So you can catch it in KeyPress Event like this:
private void btnTarget_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar != 3) // if it is not Ctrl + C
{
// do something
}
}
Try the following: capture the up arrow and down arrow events. When you detect down arrow for CTRL, set a flag; when you detect up arrow, reset the flag. If you detect the C key while the flag is set, you have Ctrl+C.
Edit. Ouch... Jay's answer is definitely better. :-)
I don't know if it's because some change in newer version or because I am trying to use this on ListBox, but there is no e.Control in KeyEventArgs e that I get from KeyDown.
I had to work around solution, I came up with this (it's not the prettiest one, but it works fine):
private List<Key> KeyBuff = new List<Key>();
private void ListBox_KeyDown(object sender, KeyEventArgs e)
{
if (!KeyBuff.Exists(k => k == e.Key))
KeyBuff.Add(e.Key);
if (KeyBuff.Exists(k => k == Key.LeftCtrl || k == Key.RightCtrl) &&
KeyBuff.Exists(k => k == Key.C))
{
// Desired detection
Clipboard.SetText(SelectedText);
}
}
private void ListBox_KeyUp(object sender, KeyEventArgs e)
{
KeyBuff.Clear();
}
For me, it's not working with KeyDown event so I tried with PreviewKeyDown and it's worked.
private void txt_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.Control == true && e.KeyCode == Keys.C)
{
Clipboard.SetText(txt.SelectedText);
}
}