I have an application which want to detect multiple keys on Keyboard (keydown event in c#).
In the last, i have limited keys detection (may be 4 keys) on event keydown and also i can't fire the event when "fn" keys keydown.
there are 2 question here:
1. How to detect keys as many as possible
2. How to detect Fn keys when keyboard keydown event.
Here, I us globalKeyboardHook library that i found from others solution.
private void Form1_Load(object sender, EventArgs e)
{
gkh.HookedKeys.Add(Keys.A);
gkh.HookedKeys.Add(Keys.B);
gkh.HookedKeys.Add(Keys.D);
gkh.HookedKeys.Add(Keys.F);
gkh.HookedKeys.Add(Keys.G);
gkh.HookedKeys.Add(Keys.H);
gkh.HookedKeys.Add(Keys.J);
gkh.HookedKeys.Add(Keys.K);
gkh.HookedKeys.Add(Keys.L);
gkh.HookedKeys.Add(Keys.Z);
gkh.HookedKeys.Add(Keys.X);
gkh.HookedKeys.Add(Keys.C);
gkh.HookedKeys.Add(Keys.V);
gkh.HookedKeys.Add(Keys.B);
gkh.HookedKeys.Add(Keys.N);
gkh.HookedKeys.Add(Keys.M);
gkh.HookedKeys.Add(Keys.Q);
gkh.HookedKeys.Add(Keys.W);
gkh.HookedKeys.Add(Keys.E);
gkh.HookedKeys.Add(Keys.R);
gkh.HookedKeys.Add(Keys.T);
gkh.HookedKeys.Add(Keys.Y);
gkh.HookedKeys.Add(Keys.U);
gkh.HookedKeys.Add(Keys.I);
gkh.HookedKeys.Add(Keys.O);
gkh.HookedKeys.Add(Keys.P);
gkh.HookedKeys.Add(Keys.NumLock);
gkh.HookedKeys.Add(Keys.Insert);
gkh.HookedKeys.Add(Keys.FinalMode);
gkh.KeyDown += new KeyEventHandler(gkh_KeyDown);
}
void gkh_KeyDown(object sender, KeyEventArgs e)
{
Console.WriteLine(e.KeyCode.ToString());
e.Handled = true;
}
I am really pleasure, if you can help me.
thanks.
You can't get a KeyDown event with multiple keys.
However, you can either check for keys that are currently pressed, or you can keep track of all those that are Down at the moment (record them when you get KeyDown and remove when you get KeyUp).
There is a fixed limit to keys being pressed simultaneously based on the hardware keyboard. It may very well be that some key combinations only allow you to register two keys simultaneously, while others are more useable. And of course, there's gaming keyboards that can easily keep track of 20 or more at a time.
There is a managed library MouseKeyHook as nuget which has support for detecting shortcuts, key combinations and sequences. Source code on github. Here is a usage example:
void DoSomething()
{
Console.WriteLine("You pressed UNDO");
}
Hook.AppEvents().OnCombination(new Dictionary<Combination, Action>
{
{Combination.FromString("Control+Z"), DoSomething},
{Combination.FromString("Shift+Alt+Enter"), () => { Console.WriteLine("You Pressed FULL SCREEN"); }}
});
For more information see: Detecting Key Combinations and Seuqnces
Related
I have managed to determine if capslock is on or off, so that I can display proper error message. But my code works only, if capslock is off when textbox gets focus. But if it is on, then error message appears when it shouldn't.
private Boolean CapsLock = false; //here...how to determine if it is on or off propperly
private void loginCredentials_KeyUp(object sender, KeyRoutedEventArgs e)
{
switch (e.Key.GetHashCode())
{
//...
case 20:
CapsLock = (CapsLock) ? false : true;
errorMessage.Text = (CapsLock) ? ((App)(App.Current)).loader.GetString("capslockError") : String.Empty;
break;
}
}
The WinRT method to find the current key status is GetKeyState, so you can check the key value directly if you need to (similar to the IsKeyLocked mentioned in comments).
I'd note that switching on the hashcode of the key pressed seems wrong, you should check the key value itself against the code from the VirtualKey enum (I guess you've noticed that the hash code is just this value, meaning that it works).
If you do need to know immediately when a key such as the caps lock is pressed in general, not just when your text field has focus, you can register a key handler on the application root visual. Normally key presses will be consumed by controls like a text box that handle them, but you can use AddHandler with true parameter to listen to all key presses including handled ones, something like:
Window.Current.AddHandler(UIElement.KeyUpEvent, new KeyEventHandler(...), true);
Or alternatively use the Window.Current.CoreWindow.KeyUp event.
I am creating a piano in C Sharp and currently I have keyboard keys to play sounds. For example key A plays Note C. problem I am having is there I want to be pressing multiple keys at the same time and have the sound out. obviously I don't want to have to put all combinations in the keyDown class as I will have to make thousands of if statements. Is there anyway around this?
Windows works with an only one message queue, so in each time only a key down message will be handled at a time unit. What you can do is to get all key down events in a short time interval (0.5 seconds for instace), save all key pressed in a list or a queue, then play all sounds according to the keys asynchronically (using threads). I have never have done this before, but I think should works. Hope helps...
EDIT
Ok, let see:
first the list where to save the keys
List<Key> _keys = new List<Key>();
Then start a timer for checking the keys pressed in a time interval:
var t = new System.Timers.Timer(500); //you may try using an smaller value
t.Elapsed += t_Elapsed;
t.Start();
Then the t_Elapsed method (Note that if you are in WPF an DispatcherTimer should be used, this timer is on System.Timers)
void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (_keys.Count > 0)
{
//Here get all keys and play the sound using threads
_keys.Clear();
}
}
And then the on key down method:
void OnKeyDownMethod(object sender, KeyPressedEventArgs e) //not sure this is the name of the EventArgs class
{
_keys.Add(e.Key); //need to check
}
You may try this, hope be helpful.
How can I detect if any keyboard key is currently being pressed? I'm not interested in what the key is, I just want to know if any key is still pressed down.
if (Keyboard.IsKeyDown(Key.ANYKEY??)
{
}
public static IEnumerable<Key> KeysDown()
{
foreach (Key key in Enum.GetValues(typeof(Key)))
{
if (Keyboard.IsKeyDown(key))
yield return key;
}
}
you could then do:
if(KeysDown().Any()) //...
If you want to detect key pressed only in our application (when your WPF window is activated) add KeyDown like below:
public MainWindow()
{
InitializeComponent();
this.KeyDown += new KeyEventHandler(MainWindow_KeyDown);
}
void MainWindow_KeyDown(object sender, KeyEventArgs e)
{
MessageBox.Show("You pressed a keyboard key.");
}
If you want to detect when a key is pressed even your WPF window is not active is a little harder but posibile. I recomend RegisterHotKey (Defines a system-wide hot key) and UnregisterHotKey from Windows API. Try using these in C# from pinvoke.net or these tutorials:
Global Hotkeys: Register a hotkey that is triggered even when form isn't focused.
Simple steps to enable Hotkey and ShortcutInput user control
Thse is a sample in Microsoft Forums.
You will use Virtual-Key Codes.
I Hope that I was clear and you will understand my answer.
Iterate over the System.Windows.Input.Key enum values.
public static bool IsAnyKeyDown()
{
var values = Enum.GetValues(typeof(Key));
foreach (var v in values)
if (((Key)v) != Key.None && Keyboard.IsKeyDown((Key)v)
return true;
return false;
}
Good answer here...get the set of all the keystates at once using GetKeyboardState():
Detect if any key is pressed in C# (not A, B, but any)
The above is checking the live state of the keyboard.
If you rely on hooking events up to the KeyDown/KeyUp events to track the state of the keyboard...then this may not be so accurate.
That's becuase you are relying on the message pumping to process and dispatch those KeyDown/KeyUp messages....they may be delivered after the real keyboard state has changed again.
Also because when your bit of code that is interested in the keyboard state is running (usually on the UI thread)...the KeyDown or KeyUp can't interrupt you...as they are dispatched on the UI thread too....that's why using GetKeyBoardState() or the Keyboard.IsKeyDown should be used.
(the above is assuming you want and care about the live state)
First of all I need to make it clear that I have no interest in keylogging.
I need a way to monitor keyboard activity at the most basic level while my application is in the background.
I don't need to know which keys, I don't need to save any data, I don't need or plan to hide my application at all, all I need is to know when keys are pressed and invoke a method.
I'm looking for the simplest way to do this possible, I know a reasonable amount of C# but nothing too complex as most of my knowledge is self-taught.
I've looked around for some appropriate ways of doing this and I've found nothing useful. All I've found is a bunch of people saying "No, that's illegal" on forums and source code for in depth keyloggers.
If any of you could advise me on a way to achieve this then I would be most appreciative.
You'll need to use Window Hooks:
Low-Level Keyboard Hook in C#
But beware, Windows security, may be protecting us from doing what you want!
You can monitor keyboard and mouse activity in the background with the Nuget package MouseKeyHook (GitHub).
This code detects when a key is pressed:
private IKeyboardMouseEvents _globalHook;
private void Subscribe()
{
if (_globalHook == null)
{
// Note: for the application hook, use the Hook.AppEvents() instead
_globalHook = Hook.GlobalEvents();
_globalHook.KeyPress += GlobalHookKeyPress;
}
}
private static void GlobalHookKeyPress(object sender, KeyPressEventArgs e)
{
Console.WriteLine("KeyPress: \t{0}", e.KeyChar);
}
private void Unsubscribe()
{
if (_globalHook != null)
{
_globalHook.KeyPress -= GlobalHookKeyPress;
_globalHook.Dispose();
}
}
You will need to call Subscribe() to start listening, and Unsubscribe() to stop listening. Obviously you need to modify GlobalHookKeyPress() to do useful work.
I needed this functionality in order to write a utility which will turn on the keyboard backlight on a Lenovo Thinkpad when any key is pressed, including CTRL (which KeyPress doesn't catch). For this purpose, I had to monitor for key down instead. The code is the same except we attach to a different event...
_globalHook.KeyDown += GlobalHookOnKeyDown;
and the event handler signature is different:
private static void GlobalHookOnKeyDown(object sender, KeyEventArgs e)
{
Console.WriteLine("KeyDown: \t{0}", e.KeyCode);
}
The library can also detect specific key combinations and sequences. For example:
Hook.GlobalEvents().OnCombination(new Dictionary<Combination, Action>
{
{ Combination.TriggeredBy(Keys.A).Control(), () => { Console.WriteLine("You Pressed CTRL+A"); } },
{ Combination.FromString("Shift+Alt+Enter"), () => { Console.WriteLine("You Pressed FULL SCREEN"); } }
});
Microsoft tells you How to: Handle Keyboard Input at the Form Level. As long as you handle the same event(s) this works for any non web application.
You should also take a look at the other questions here on SO, such as Handling Input from a Keyboard Wedge
You could register Windows Hot Key with RegisterHotKey windows API, look at this blog post :
http://www.liensberger.it/web/blog/?p=207
In a C# Console app, pressing the Pause key freezes the display output. Can I disable that?
I was hoping for a handler like the Console.CancelKeyPress event that handles Ctrl+C input.
Every once in a while a request comes up for hooking keys from a console program. The standard events like CTRL_C_EVENT and CTRL_CLOSE_EVENT do not include the Pause-event. I've tried doing so using a background thread, but I don't seem to manage. However, there's a not-so-hard workaround: use an extra process.
Download this easy-to-use global keyboard hook for C#. Then, when you open that project, take the following code and put it in the Form1.cs:
public partial class Form1 : Form {
globalKeyboardHook globalKeyboardHook = new globalKeyboardHook();
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
globalKeyboardHook.HookedKeys.Add(Keys.Pause);
globalKeyboardHook.KeyDown += new KeyEventHandler(globalKeyboardHook_KeyDown);
globalKeyboardHook.KeyUp += new KeyEventHandler(globalKeyboardHook_KeyUp);
}
void globalKeyboardHook_KeyUp(object sender, KeyEventArgs e)
{
// remove this when you want to run invisible
lstLog.Items.Add("Up\t" + e.KeyCode.ToString());
// this prevents the key from bubbling up in other programs
e.Handled = true;
}
void globalKeyboardHook_KeyDown(object sender, KeyEventArgs e)
{
// remove this when you want to run without visible window
lstLog.Items.Add("Down\t" + e.KeyCode.ToString());
// this prevents the key from bubbling up in other programs
e.Handled = true;
}
}
Then, the rest becomes trivial:
Change your program to start the above program and than run normally
Try to type the pause key
It'll be caught by the other program
Your program will NOT be paused.
I tried the above myself and it works.
PS: I don't mean that there isn't a possible way straight from a Console program. There may very well be, I just didn't find it, and the above global keyhook library didn't work from within a Console application.
It's not necessary to attach an hook for this. In your case #PeteVasi, you can modify the console mode to capture Ctrl+C, Ctrl+S, etc... events that are not normally possible to capture.
See my answer to a similar question here.