Detect if Modifier Key is Pressed in KeyRoutedEventArgs Event - c#

I have the following code:
public void tbSpeed_KeyDown(object sender, KeyRoutedEventArgs e)
{
e.Handled = !((e.Key >= 48 && e.Key <= 57) || (e.Key >= 96 && e.Key <= 105) || (e.Key == 109) || (e.Key == 189));
}
Is there any way to detect if any modifier key like shift is being pressed ?

Use GetKeyState. e.g.
var state = CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Shift);
return (state & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;
Note: For Alt, you would use VirtualKey.Menu.

For Win10 UWP I noticed that the CTRL and SHIFT keys were set at Locked state. So I did the following:
var shiftState = CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Shift);
var ctrlState = CoreWindow.GetForCurrentThread().GetKeyState(VirtualKey.Control);
var isShiftDown = shiftState != CoreVirtualKeyStates.None;
var isCtrlDown = ctrlState != CoreVirtualKeyStates.None;

You can try the following code
CoreVirtualKeyStates controlKeyState = Window.Current.CoreWindow.GetKeyState(VirtualKey.Control);
var ctrl = (controlKeyState & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;
CoreVirtualKeyStates shiftKeyState = Window.Current.CoreWindow.GetKeyState(VirtualKey.Shift);
var shift = (shiftKeyState & CoreVirtualKeyStates.Down) == CoreVirtualKeyStates.Down;

Bitwise AND the Modifiers property of Keyboard with Shift Key -
bool isShiftKeyPressed = (Keyboard.Modifiers & ModifierKeys.Shift)
== ModifierKeys.Shift;
Try this too-
bool isShiftKeyPressed = (ModifierKeys & Keys.Shift) == Keys.Shift;
OR
Control.ModifierKeys == Keys.Shift

Related

prevent shortcuts with wpf webbrowser

hey I have a problem with my wpf webbrowser. I dont want that you can press shortcuts like "CRTL + N" for a new tab for example. I already found out how to do it, but if I want to handle more shortcuts it will only prevent the last one. I know that this will be very simple but I dont know how to fix it at the moment. Here is my code:
e.Handled = e.Key == Key.N && e.KeyboardDevice.Modifiers == ModifierKeys.Control;
e.Handled = e.Key == Key.O && e.KeyboardDevice.Modifiers == ModifierKeys.Control;
e.Handled = e.Key == Key.OemMinus && e.KeyboardDevice.Modifiers == ModifierKeys.Control;
e.Handled = e.Key == Key.OemPlus && e.KeyboardDevice.Modifiers == ModifierKeys.Control;
e.Handled = e.Key == Key.Subtract && e.KeyboardDevice.Modifiers == ModifierKeys.Control;
e.Handled = e.Key == Key.Add && e.KeyboardDevice.Modifiers == ModifierKeys.Control;
You need to OR together your conditions.
e.Handled = ((e.Key == Key.N) && (e.KeyboardDevice.Modifiers == ModifierKeys.Control)) ||
((e.Key == Key.O) && (e.KeyboardDevice.Modifiers == ModifierKeys.Control)) ||
((e.Key == Key.OemMinus) && (e.KeyboardDevice.Modifiers == ModifierKeys.Control)) ||
((e.Key == Key.OemPlus) && (e.KeyboardDevice.Modifiers == ModifierKeys.Control)) ||
((e.Key == Key.Subtract) && (e.KeyboardDevice.Modifiers == ModifierKeys.Control)) ||
((e.Key == Key.Add) && (e.KeyboardDevice.Modifiers == ModifierKeys.Control));
As Modifier CTRL appears to be common, this can be separated out from the keys & the simplified code would be something like
e.Handled = (e.KeyboardDevice.Modifiers == ModifierKeys.Control) &&
((e.Key == Key.N) || (e.Key == Key.O) || (e.Key == Key.OemMinus) || ...... )
Note that I have added brackets that some people will say are unnecessary, but I prefer them for readability.

Masked TextBox with decimal numbers

In my window application I need masked textbox which accept real decmal numbers.
eg.
1) 1.56
2) 22.34
3) 123.34
4) 12312.34
This all value should be valid.
Can anyone tell me how can I do this?
And ya if anyone have better solution for real decimal numbers, instead of this masked TextBox
than I love to see it.
Thanks...
Instead of using a MaskedTextbox, consider using NumericUpDown instead. It supports System.Decimal numbers which supports most real-set numbers you should be caring about.
The NumericUpDown.DecimalPlaces property supports up to 99 decimal places.
Use a custom control like this one (modify it to fulfill your needs):
using System;
using System.ComponentModel;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace CustomControls
{
public enum PasteRejectReasons
{
Unknown = 0,
NoData,
InvalidCharacter,
Accepted
}
public class DecimalTextBox : TextBox
{
public const int WM_PASTE = 0x0302;
public event EventHandler<KeyRejectedEventArgs> KeyRejected;
public event EventHandler<PasteEventArgs> PasteRejected;
private bool _DecimalSeparator = false;
private int _Precision;
public new HorizontalAlignment TextAlign
{
get { return base.TextAlign; }
set { base.TextAlign = value; }
}
public int Precision
{
get { return _Precision; }
set { _Precision = value; }
}
public DecimalTextBox()
{
TextAlign = HorizontalAlignment.Right;
Precision = 3;
}
protected override void OnGotFocus(EventArgs e)
{
SelectAll();
base.OnGotFocus(e);
}
protected override void OnKeyDown(KeyEventArgs e)
{
bool validate = true;
if (Text.Contains(".") || Text.Contains(","))
{
int indexSep;
string[] split;
string partiDecimal = "";
if (Text.Contains("."))
indexSep = Text.IndexOf('.');
else
indexSep = Text.IndexOf(',');
split = Text.Split(new char[] { ',', '.' });
partiDecimal += split[1];
if (partiDecimal.Length >= Precision)
if (SelectionStart > Text.Length - (partiDecimal.Length + 1))
validate = false;
}
bool result = true;
bool validateKeys = (e.KeyCode == Keys.Enter);
bool numericKeys = (
((e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9) ||
(e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9))
&& e.Modifiers != Keys.Shift
&& validate);
bool ctrlA = e.KeyCode == Keys.A && e.Modifiers == Keys.Control;
bool editKeys = (
(e.KeyCode == Keys.Z && e.Modifiers == Keys.Control) ||
(e.KeyCode == Keys.X && e.Modifiers == Keys.Control) ||
(e.KeyCode == Keys.C && e.Modifiers == Keys.Control) ||
(e.KeyCode == Keys.V && e.Modifiers == Keys.Control) ||
e.KeyCode == Keys.Delete ||
e.KeyCode == Keys.Back);
bool navigationKeys = (
e.KeyCode == Keys.Up ||
e.KeyCode == Keys.Right ||
e.KeyCode == Keys.Down ||
e.KeyCode == Keys.Left ||
e.KeyCode == Keys.Home ||
e.KeyCode == Keys.End);
bool decimalSeparator = ((
e.KeyCode == Keys.Decimal ||
e.KeyValue == 190 ||
e.KeyValue == 188)&&
TextLength != 0 &&
SelectionLength == 0);
if (decimalSeparator)
{
if (!_DecimalSeparator)
_DecimalSeparator = true;
else
decimalSeparator = false;
}
if (!(numericKeys || editKeys || navigationKeys || decimalSeparator || validateKeys))
{
if (ctrlA)
SelectAll();
result = false;
}
if (!result)
{
e.SuppressKeyPress = true;
e.Handled = true;
if (!ctrlA)
OnKeyRejected(new KeyRejectedEventArgs(e.KeyCode));
}
else
base.OnKeyDown(e);
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (e.KeyChar == ';' || e.KeyChar == '?')
{
if (!(Text.Contains(",") || Text.Contains(".")))
_DecimalSeparator = false;
e.Handled = true;
}
}
protected override void OnTextChanged(EventArgs e)
{
bool invalid = false;
int i = 0;
foreach (char c in Text) // Check for any non digit characters.
{
if (!(char.IsDigit(c) || c == ',' || c == '.'))
{
invalid = true;
break;
}
if (c == ',' || c == '.')
i++;
}
if (i == 0)
_DecimalSeparator = false;
else if (i > 1)
invalid = true;
if (invalid)
{
Text = "";
return;
}
if (Text.Contains(".") || Text.Contains(","))
{
string charSep = "";
string[] split;
string partiEntier = "";
if (Text.Contains("."))
charSep = ".";
else
charSep = ",";
split = Text.Split(new char[] { ',', '.' });
partiEntier += split[0];
if (partiEntier == "")
Text = "0" + charSep + split[1];
}
base.OnTextChanged(e);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_PASTE)
{
PasteEventArgs e = CheckPasteValid();
if (e.RejectReason != PasteRejectReasons.Accepted)
{
m.Result = IntPtr.Zero;
OnPasteRejected(e);
return;
}
}
base.WndProc(ref m);
}
private PasteEventArgs CheckPasteValid()
{
PasteRejectReasons rejectReason = PasteRejectReasons.Accepted;
string originalText = Text;
string clipboardText = string.Empty;
string textResult = string.Empty;
try
{
clipboardText = Clipboard.GetText(TextDataFormat.Text);
if (clipboardText.Length > 0)
{
textResult = (
Text.Remove(SelectionStart, SelectionLength).Insert(SelectionStart, clipboardText));
foreach (char c in clipboardText)
{
if (!char.IsDigit(c))
{
rejectReason = PasteRejectReasons.InvalidCharacter;
break;
}
}
}
else
rejectReason = PasteRejectReasons.NoData;
}
catch
{
rejectReason = PasteRejectReasons.Unknown;
}
return new PasteEventArgs(originalText, clipboardText, textResult, rejectReason);
}
protected virtual void OnKeyRejected(KeyRejectedEventArgs e)
{
EventHandler<KeyRejectedEventArgs> handler = KeyRejected;
if (handler != null)
handler(this, e);
}
protected virtual void OnPasteRejected(PasteEventArgs e)
{
EventHandler<PasteEventArgs> handler = PasteRejected;
if (handler != null)
handler(this, e);
}
}
}

Identify if a event Key is text (not only alphanumeric)

I've a textbox with an event that should do things when some text is entered. It's easy to check if it is alphanumeric as stated here Can I determine if a KeyEventArg is an letter or number? :
if ( ( ( e.KeyCode >= Keys.A && e.KeyCode <= Keys.Z ) ||
( e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9 ) ||
( e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9 ) )
The problem with this approach is that I should also check manually for -?!¿[]() with Key.OemMinus, Key.OemQuestion, etc.
Is there some way to check if it's a text keystroke or I should check manually (which is not very elegant in my opinion)?
As no other option is suggested I used the following code to allow nearly all text keystrokes. Unfortunatelly, this is keyboard dependant so it's not very elegant. Hopefully is not a critical aspect in the application, it's only a matter of usability.
bool isText = (e.Key >= Key.A && e.Key <= Key.Z) || (e.Key >= Key.D0 && e.Key <= Key.D9) || (e.Key >= Key.NumPad0 && e.Key <= Key.NumPad9)
|| e.Key == Key.OemQuestion || e.Key == Key.OemQuotes || e.Key == Key.OemPlus || e.Key == Key.OemOpenBrackets || e.Key == Key.OemCloseBrackets || e.Key == Key.OemMinus
|| e.Key == Key.DeadCharProcessed || e.Key == Key.Oem1 || e.Key == Key.Oem7 || e.Key == Key.OemPeriod || e.Key == Key.OemComma || e.Key == Key.OemMinus
|| e.Key == Key.Add || e.Key == Key.Divide || e.Key == Key.Multiply || e.Key == Key.Subtract || e.Key == Key.Oem102 || e.Key == Key.Decimal;
this code allow just numbers and '.':
private void txtJustNumber_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsDigit((char)(e.KeyChar)) &&
e.KeyChar != ((char)(Keys.Enter)) &&
e.KeyChar != (char)(Keys.Delete) &&
e.KeyChar != (char)(Keys.Back))
{
e.Handled = true;
}
}

Why not work KeyDown CTRL+KEY?

In the following code, the two calls to Zoom(0.1f); and Zoom(-0.1f); work but I cannot trigger the two UndoRedoManager.Undo(); and UndoRedoManager.Redo(); calls for CTRL+Z and CTRL+Y. What am I doing wrong?
public void WorkspaceKeyDown(KeyEventArgs e)
{
if (e.Control == true)
isCtrlPres = true;
if (e.Shift == true)
isShiftPres = true;
if (e.Control == true && e.KeyCode == Keys.Z)
{
UndoRedoManager.Undo();
}
else if (e.Control == true && e.KeyCode == Keys.Y)
{
UndoRedoManager.Redo();
}
else if (e.Control == true && e.KeyCode == Keys.Oemplus)
{
Zoom(0.1f);
}
else if (e.Control == true && e.KeyCode == Keys.OemMinus)
{
Zoom(-0.1f);
}
.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Z)));

Convert a System.Windows.Input.KeyEventArgs key to a char

I need to get the event args as a char, but when I try casting the Key enum I get completely different letters and symbols than what was passed in.
How do you properly convert the Key to a char?
This is what I've tried
ObserveKeyStroke(this, new ObervableKeyStrokeEvent((char)((KeyEventArgs)e.StagingItem.Input).Key));
Edit: I also don't have the KeyCode property on the args. I'm getting them from the InputManager.Current.PreNotifyInput event.
See How to convert a character in to equivalent System.Windows.Input.Key Enum value?
Use KeyInterop.VirtualKeyFromKey instead.
It takes a little getting used to, but you can just use the key values themselves. If you're trying to limit input to alphanumerics and maybe a little extra, the code below may help.
private bool bLeftShiftKey = false;
private bool bRightShiftKey = false;
private bool IsValidDescriptionKey(Key key)
{
//KEYS ALLOWED REGARDLESS OF SHIFT KEY
//various editing keys
if (
key == Key.Back ||
key == Key.Tab ||
key == Key.Up ||
key == Key.Down ||
key == Key.Left ||
key == Key.Right ||
key == Key.Delete ||
key == Key.Space ||
key == Key.Home ||
key == Key.End
) {
return true;
}
//letters
if (key >= Key.A && key <= Key.Z)
{
return true;
}
//numbers from keypad
if (key >= Key.NumPad0 && key <= Key.NumPad9)
{
return true;
}
//hyphen
if (key == Key.OemMinus)
{
return true;
}
//KEYS ALLOWED CONDITITIONALLY DEPENDING ON SHIFT KEY
if (!bLeftShiftKey && !bRightShiftKey)
{
//numbers from keyboard
if (key >= Key.D0 && key <= Key.D9)
{
return true;
}
}
return false;
}
private void cboDescription_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.LeftShift)
{
bLeftShiftKey = true;
}
if (e.Key == Key.RightShift)
{
bRightShiftKey = true;
}
if (!IsValidDescriptionKey(e.Key))
{
e.Handled = true;
}
}
private void cboDescription_PreviewKeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.LeftShift)
{
bLeftShiftKey = false;
}
if (e.Key == Key.RightShift)
{
bRightShiftKey = false;
}
}
That work for me:
Based on the last entry i found that in WPF there is no such event PreNotifyInput, but i found and equivalent PreviewTextInput
First I try with a RegExp, but I cant make it work, then I use a simple indexOf.
private bool ValidChar(string _char)
{
string Lista = #" ! "" # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? # A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ";
return Lista.IndexOf(_char.ToUpper()) != -1;
//System.Text.RegularExpressions.Regex RegVal = new System.Text.RegularExpressions.Regex(#"(?<LETRAS>[A-Z]+)+(?<NUMERO>[0-9]+)+(?<CAR>[!|""|#|$|%|&|'|(|)|*|+|,|\-|.|/|:|;|<|=|>|?|#]+)+");
//return RegVal.IsMatch(_char);
}
private void textBoxDescripcion_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
if (!ValidChar(e.Text))
e.Handled = true;
}
I know this is old, but none of the answers seem to actually answer the question. The reason a different char is coming back is because when you just try to cast it to a char you are casting the enum value to a 'char'. However:
var keyPressed = e.key.ToString();
Works great. Returns the key pressed as a string. Then you check the length. If it's == 1 then it's a char, number or symbol. If it's greater than 1 it's a special key.
If you just want the char you can then do keyPressed[0];
This is how I do it.
private void scrollViewer_KeyDown(object sender, KeyEventArgs e)
{
if (!e.IsRepeat)
{
var keyPressed = e.Key.ToString();
if(keyPressed.Length == 1)
CharKeyPressed(keyPressed[0]);
else if(keyPressed.Length > 1)
HandleSpecialKey(keyPressed)
}
}
Inside your PreNotifyInput handler, try something like this:
if (e.StagingItem.Input is System.Windows.Input.TextCompositionEventArgs)
{
if (!String.IsNullOrEmpty((e.StagingItem.Input as System.Windows.Input.TextCompositionEventArgs).Text))
{
Char c = (e.StagingItem.Input as System.Windows.Input.TextCompositionEventArgs).Text[0];
}
}
It raises multiple times for the different routed events, so you may want to filter for a particular one.

Categories