I am aiding in the development for a custom made application for the Motorola MC75. It is well tuned except for a random bug with the barcode reader. Periodically, the barcode reader will only activate (start a read) if the right shoulder button is pressed. The middle and left shoulder buttons somehow become disabled. This is a unique bug in that it happens randomly and only effects 2 of the three buttons. The EMDK enables all buttons simultaneously so I am clueless as to where this is coming from (Internal or code related). If anyone has any input or advice please let me know and thank you beforehand.
Thanks,
Zach
I've worked with the Motorola EMDK before on the MC55. I'm not sure why the buttons are being disabled, and since you posted this in June you probably don't need the answer anymore, but here's a possible workaround:
Instead of letting the EMDK handle the triggers on its own, you can capture all triggers by setting up an event:
// Create a trigger device to handle all trigger events of stage 2 (pressed) or RELEASED
var device = new TriggerDevice(TriggerID.ALL_TRIGGERS, new[] { TriggerState.RELEASED, TriggerState.STAGE2 });
var trigger = new Trigger(device);
trigger.Stage2Notify += OnTrigger;
Then, in your OnTrigger method, you can handle the trigger and perform the appropriate action. For example, you can activate your barcode reader when any trigger is pressed:
private void OnTrigger(object sender, TriggerEventArgs e)
{
if (e.NewState == e.PreviousState)
return;
// Pseudocode
if (e.NewState == TriggerState.RELEASED)
{
myBarcodeReader.Actions.ToggleSoftTrigger();
myBarcodeReader.Actions.Flush();
myBarcodeReader.Actions.Disable();
}
else if (e.NewState == TriggerState.STAGE2)
{
// Prepare the barcode reader for scanning
// This initializes various objects but does not actually enable the scanner device
// The scanner device would still need to be triggered either via hardware or software
myBarcodeReader.Actions.Enable();
myBarcodeReader.Actions.Read(data);
// Finally, turn on the scanner via software
myBarcodeReader.Actions.ToggleSoftTrigger();
}
}
Related
I have a barcode scanner (which acts like a keyboard) and of course I have a keyboard too hooked up to a computer. The software is accepting input from both the scanner and the keyboard. I need to accept only the scanner's input. The code is written in C#. Is there a way to "disable" input from the keyboard and only accept input from the scanner?
Note:
Keyboard is part of a laptop...so it cannot be unplugged. Also, I tried putting the following code
protected override Boolean ProcessDialogKey(System.Windows.Forms.Keys keyData)
{
return true;
}
But then along with ignoring the keystrokes from the keyboard, the barcode scanner input is also ignored.
I cannot have the scanner send sentinal characters as, the scanner is being used by other applications and adding a sentinal character stream would mean modifying other code.
Also, I cannot use the timing method of determining if the input came from a barcode scanner (if its a bunch of characters followed by a pause) since the barcodes scanned could potentially be single character barcodes.
Yes, I am reading data from a stream.
I am trying to follow along with the article: Distinguishing Barcode Scanners from the Keyboard in WinForms. However I have the following questions:
I get an error NativeMethods is inaccessible due to its protection level. It seems as though I need to import a dll; is this correct? If so, how do I do it?
Which protected override void WndProc(ref Message m) definition should I use, there are two implementations in the article?
Am getting an error related to [SecurityPermission( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] error CS0246: The type or namespace name 'SecurityPermission' could not be found (are you missing a using directive or an assembly reference?). How do I resolve this error?
There is also an error on the line containing: if ((from hardwareId in hardwareIds where deviceName.Contains(hardwareId) select hardwareId).Count() > 0) Error is error CS1026: ) expected.
Should I be placing all the code in the article in one .cs file called BarcodeScannerListener.cs?
Followup questions about C# solution source code posted by Nicholas Piasecki on http://nicholas.piasecki.name/blog/2009/02/distinguishing-barcode-scanners-from-the-keyboard-in-winforms/:
I was not able to open the solution in VS 2005, so I downloaded Visual C# 2008 Express Edition, and the code ran. However, after hooking up my barcode scanner and scanning a barcode, the program did not recognize the scan. I put a break point in OnBarcodeScanned method but it never got hit. I did change the App.config with the id of my Barcode scanner obtained using Device Manager. There seems to be 2 deviceNames with HID#Vid_0536&Pid_01c1 (which is obtained from Device Manager when the scanner is hooked up). I don't know if this is causing the scanning not to work. When iterating over the deviceNames, here is the list of devices I found (using the debugger):
"\??\HID#Vid_0536&Pid_01c1&MI_01#9&25ca5370&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}"
"\??\HID#Vid_0536&Pid_01c1&MI_00#9&38e10b9&0&0000#{884b96c3-56ef-11d1-bc8c-00a0c91405dd}"
"\??\HID#Vid_413c&Pid_2101&MI_00#8&1966e83d&0&0000#{884b96c3-56ef-11d1-bc8c-00a0c91405dd}"
"\??\HID#Vid_413c&Pid_3012#7&960fae0&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}"
"\??\Root#RDP_KBD#0000#{884b96c3-56ef-11d1-bc8c-00a0c91405dd}"
"\??\ACPI#PNP0303#4&2f94427b&0#{884b96c3-56ef-11d1-bc8c-00a0c91405dd}"
"\??\Root#RDP_MOU#0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}"
"\??\ACPI#PNP0F13#4&2f94427b&0#{378de44c-56ef-11d1-bc8c-00a0c91405dd}"
So there are 2 entries for HID#Vid_0536&Pid_01c1; could that be causing the scanning not to work?
OK so it seems that I had to figure out a way to not depend on the ASCII 0x04 character being sent by the scanner...since my scanner does not send that character. After that, the barcode scanned event is fired and the popup with the barcode is shown. So thanks Nicholas for your help.
You could use the Raw Input API to distinguish between the keyboard and the scanner like I did recently. It doesn't matter how many keyboard or keyboard-like devices you have hooked up; you will see a WM_INPUT before the keystroke is mapped to a device-independent virtual key that you typically see in a KeyDown event.
Far easier is to do what others have recommended and configure the scanner to send sentinel characters before and after the barcode. (You usually do this by scanning special barcodes in the back of the scanner's user manual.) Then, your main form's KeyPreview event can watch those roll end and swallow the key events for any child control if it's in the middle of a barcode read. Or, if you wanted to be fancier, you could use a low-level keyboard hook with SetWindowsHookEx() to watch for those sentinels and swallow them there (advantage of this is you could still get the event even if your app didn't have focus).
I couldn't change the sentinel values on our barcode scanners among other things so I had to go the complicated route. Was definitely painful. Keep it simple if you can!
--
Your update, seven years later: If your use case is reading from a USB barcode scanner, Windows 10 has a nice, friendly API for this built-in in Windows.Devices.PointOfService.BarcodeScanner. It's a UWP/WinRT API, but you can use it from a regular desktop app as well; that's what I'm doing now. Here's some example code for it, straight from my app, to give you the gist:
{
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using Windows.Devices.Enumeration;
using Windows.Devices.PointOfService;
using Windows.Storage.Streams;
using PosBarcodeScanner = Windows.Devices.PointOfService.BarcodeScanner;
public class BarcodeScanner : IBarcodeScanner, IDisposable
{
private ClaimedBarcodeScanner scanner;
public event EventHandler<BarcodeScannedEventArgs> BarcodeScanned;
~BarcodeScanner()
{
this.Dispose(false);
}
public bool Exists
{
get
{
return this.scanner != null;
}
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
public async Task StartAsync()
{
if (this.scanner == null)
{
var collection = await DeviceInformation.FindAllAsync(PosBarcodeScanner.GetDeviceSelector());
if (collection != null && collection.Count > 0)
{
var identity = collection.First().Id;
var device = await PosBarcodeScanner.FromIdAsync(identity);
if (device != null)
{
this.scanner = await device.ClaimScannerAsync();
if (this.scanner != null)
{
this.scanner.IsDecodeDataEnabled = true;
this.scanner.ReleaseDeviceRequested += WhenScannerReleaseDeviceRequested;
this.scanner.DataReceived += WhenScannerDataReceived;
await this.scanner.EnableAsync();
}
}
}
}
}
private void WhenScannerDataReceived(object sender, BarcodeScannerDataReceivedEventArgs args)
{
var data = args.Report.ScanDataLabel;
using (var reader = DataReader.FromBuffer(data))
{
var text = reader.ReadString(data.Length);
var bsea = new BarcodeScannedEventArgs(text);
this.BarcodeScanned?.Invoke(this, bsea);
}
}
private void WhenScannerReleaseDeviceRequested(object sender, ClaimedBarcodeScanner args)
{
args.RetainDevice();
}
private void Dispose(bool disposing)
{
if (disposing)
{
this.scanner = null;
}
}
}
}
Granted, you'll need a barcode scanner that supports the USB HID POS and isn't just a keyboard wedge. If your scanner is just a keyboard wedge, I recommend picking up something like a used Honeywell 4600G off eBay for like $25. Trust me, your sanity will be worth it.
What I did in a similar situation is distinguish between a scan and a user typing by looking at the speed of the input.
Lots of characters very close together then a pause is a scan. Anything else is keyboard input.
I don't know exactly your requirements, so maybe that won't do for you, but it's the best I've got :)
It depends on the way you are interacting with the device. Anyway it wont be a C# solution, it will be some other library. Are you reading data from a stream? If you are just taking keystrokes, there may be nothing you can do about it.
I know this is an old thread, found it by searching barcode scanning in WIN10.
Just a few notes in case someone needs it.
These scanners from Honeywell have several USB interfaces.
One is a keyboard + Hid Point of sales (composite device).
Also there are CDC-ACM (ComPort emulation) and Hid Point of sales (alone) + more.
By default the scanners expose a serial number, so the host can distinguish between many devices (I had once +20 connected). There is a command to disable the serial number though!
The newer models behave the same in this regard.
If you want to see it live, try my terminal program yat3 (free on my site).
It can open all the interfaces mentioned above and is tailored for such devices.
A word to use keyboard interfaces:
Only use them as a last resort. They are slow, less reliable when it comes to exotic characters. The only good use is if you want to enter data into existing applications. If you code anyway, then reading from ComPort/HidPos-Device is easier.
look at this: http://nate.dynalias.net/dev/keyboardredirector.rails (NOT AVAILABLE ANYMORE) works great!
Specify the keyboard and the keys you want to block, and it works like a charm!
Also take a look at this: http://www.oblita.com/interception.html
You can create a C# wrapper for it - it also works like a charm..
I think you might be able to distinguish multiple keyboards through DirectX API, or if that doesn't work, through raw input API.
I have successfully accomplished what you folks are looking for here. I have an application that receives all barcode character data from a Honeywell/Metrologic barcode scanner. No other application on the system receives the data from the scanner, and the keyboard continues to function normally.
My application uses a combination of raw input and the dreaded low-level keyboard hook system. Contrary to what is written here, I found that the wm_input message is received before the keyboard hook function is called. My code to process the wm_input message basically sets a boolean variable to specify whether or not the received character is from the scanner. The keyboard hook function, called immediately after the wm_input is processed, swallows the scanner’s pseudo-keyboard data, preventing the data from being received by other applications.
The keyboard hook function has to be placed in an dll since you want to intercept all system keyboard messages. Also, a memory mapped file has to be used for the wm_input processing code to communicate with the dll.
Hello i have a line of code that should quit the game upon pressing the three hardware button on the bottom like Menu, Home, Back
it seems that the back and the home only is working but the menu is not working
I have a Xiaomi Redmi Note 4X phone, how am i suppose to fix this issue?
Is it the same "Menu" as the other phone where when you press it, it'll show list of the opened app
here's the code:
if (Input.GetKey (KeyCode.Home) || Input.GetKey (KeyCode.Escape) || Input.GetKey (KeyCode.Menu))
{
Save ();
System.Diagnostics.Process.GetCurrentProcess ().Kill ();
}
Is it the same "Menu" as the other phone where when you press it,
it'll show list of the opened ap
Yes.
I have a Xiaomi Redmi Note 4X phone, how am i suppose to fix this
issue?
It should work otherwise it is a bug and you should file for a bug request. Before you file for abug request, use the script below to make that the Menu key is not mapped to another key.
public class KeyCodeFinder : MonoBehaviour
{
public Text text;
Array allKeyCodes;
void Start()
{
allKeyCodes = System.Enum.GetValues(typeof(KeyCode));
}
void Update()
{
foreach (KeyCode tempKey in allKeyCodes)
{
if (Input.GetKeyDown(tempKey))
{
text.text = "Pressed: KeyCode." + tempKey;
Debug.Log("Pressed: KeyCode." + tempKey);
}
}
}
}
Meanwhile, you can make a Java plugin that calls your C# function when the Menu keycode is pressed. That's another option you have.
Those buttons are OS related, you don't really control what happens with those. Well, you can track them and kill your app but this is going against what every single application does. That is, if you press the back or home or quit, it gets back to the main OS page, but your app is still on the stack ready to get back.
If you want to save when the user quits, maybe you want to look into
https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnApplicationPause.html
This will make your app behave in a more common way.
On a side note, I would even assume this kind of attempt to over control the app would be rejected for AppStore (iOS) as it would not comply with their generic requirements.
It is allways possible to map a custom KeyCode that is not mapped so far.
First find out what keycode the key has
Event e = Event.current;
if (e.isKey)
{
Debug.Log("Detected key code: " + e.keyCode);
}
Let's say this gives you 10 as keycode (a one that is not mapped in Unities KeyCode so far)
You can than simply define a new one like
KeyCode MY_HOME_BUTTON = (KeyCode) 10;
and than use it like
if(Input.MY_HOME_BUTTON)
{
...
}
If it is completely possible to catch the home button depends on the OS (most of the time those buttons cannot be catched by an app but are handled by the OS first)
How the data on card is read to POS application?
I have been told some of the information such as card no and the holder's name is displayed on to the screen of the supervisor's terminal. In order to send the card information to the POS supervisor app, Keypress() event SHOULD BE used.
How do i send card information from POS card swipe machine to POS app? because just by installing drivers and configuring payment gateways would not send data to pos app. what i must do to make that keypress() event execute? im sure the developer has to write code to get that string data from the POS card swipe machine. Would you be generous enough to go through the process and show some sample code (sample code in online or some code you would like to share) on how to do it? because there is no way from out of no where the Keypress() event executes on a card swipe?
First off, this sounds like a PCI DSS nightmare. Displaying card information on screen is a definite problem, and the following code leaves you vulnerable to keylogging and memory parsing. That said...
If you're expected to use a KeyPress event for this, I assume you're receiving the track info from a keyboard wedge MSR, which is pretty simple - it just spits out the track info in plain text. You could use a KeyPress event to handle each character entered, and then send the string on the track end sentinel (typically ?):
Let's assume for simplicity's sake that you're swiping into a WinForms TextBox:
In your Form Designer select your text box, go to Events and add a KeyPress handler, or alternatively in your Form's InitializeComponent() method, attach it manually:
this.textBox1.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.textBox1_KeyPress);
Then define your KeyPress event in the Form's code-behind:
private StringBuilder trackInfo;
private bool track1Complete = false;
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar != '?' && !track1Complete)
{
trackInfo.Append(e.KeyChar);
}
else if (e.KeyChar == '?' && !track1Complete)
{
trackInfo.Append(e.KeyChar);
trackInfo.AppendLine();
track1Complete = true;
}
else if (e.KeyChar != '?' && track1Complete)
{
trackInfo.Append(e.KeyChar);
}
else if (e.KeyChar == '?' && track1Complete)
{
trackInfo.Append(e.KeyChar);
trackInfo.AppendLine();
sendTrackInfo();
}
}
What we're doing here is parsing the KeyChar on each KeyPress event argument triggered by the swipe. ? is the typical end sentinel for a single track, and there are two tracks that are considered necessary for processing a card (see here for more on the format: http://en.wikipedia.org/wiki/Magnetic_stripe_card#Financial_cards) - so we consider the card info completed at the end of the second track.
You're going to need to define the sendTrackInfo() method referenced above to format (remove sentinels, separate, etc) and send the track data you've collected in trackInfo.ToString() to your supervisor app, possibly in XML or as a stream.
I'm writing an application that can take several different external inputs (keyboard presses, motion gestures, speech) and produce similar outputs (for instance, pressing "T" on the keyboard will do the same thing as saying the word "Travel" out loud). Because of that, I don't want any of the input managers to know about each other. Specifically, I don't want the Kinect manager (as much as possible) to know about the Speech manager and vice versa, even though I'm using the Kinect's built-in microphone (the Speech manager should work with ANY microphone). I'm using System.Speech in the Speech manager as opposed to Microsoft.Speech.
I'm having a problem where as soon as the Kinect motion recognition module is enabled, the speech module stops receiving input. I've tried a whole bunch of things like inverting the skeleton stream and audio stream, capturing the audio stream in different ways, etc. I finally narrowed down the problem: something about how I'm initializing my modules does not play nicely with how my application deals with events.
The application works great until motion capture starts. If I completely exclude the Kinect module, this is how my main method looks:
// Main.cs
public static void Main()
{
// Create input managers
KeyboardMouseManager keymanager = new KeyboardMouseManager();
SpeechManager speechmanager = new SpeechManager();
// Start listening for keyboard input
keymanager.start();
// Start listening for speech input
speechmanager.start()
try
{
Application.Run();
}
catch (Exception ex)
{
MessageBox.Show(ex.StackTrace);
}
}
I'm using Application.Run() because my GUI is handled by an outside program. This C# application's only job is to receive input events and run external scripts based on that input.
Both the keyboard and speech modules receive events sporadically. The Kinect, on the other hand, generates events constantly. If my gestures happened just as infrequently, a polling loop might be the answer with a wait time between each poll. However, I'm using the Kinect to control mouse movement... I can't afford to wait between skeleton event captures, because then the mouse would be very laggy; my skeleton capture loop needs to be as constant as possible. This presented a big problem, because now I can't have my Kinect manager on the same thread (or message pump? I'm a little hazy on the difference, hence why I think the problem lies here): from the way I understand it, being on the same thread would not allow keyboard or speech events to consistently get through. Instead, I kind of hacked together a solution where I made my Kinect manager inherit from System.Windows.Forms, so that it would work with Application.Run().
Now, my main method looks like this:
// Main.cs
public static void Main()
{
// Create input managers
KeyboardMouseManager keymanager = new KeyboardMouseManager();
KinectManager kinectManager = new KinectManager();
SpeechManager speechmanager = new SpeechManager();
// Start listening for keyboard input
keymanager.start();
// Attempt to launch the kinect sensor
bool kinectLoaded = kinectManager.start();
// Use the default microphone (if applicable) if kinect isn't hooked up
// Use the kinect microphone array if the kinect is working
if (kinectLoaded)
{
speechmanager.start(kinectManager);
}
else
{
speechmanager.start();
}
try
{
// THIS IS THE PLACE I THINK I'M DOING SOMETHING WRONG
Application.Run(kinectManager);
}
catch (Exception ex)
{
MessageBox.Show(ex.StackTrace);
}
For some reason, the Kinect microphone loses its "default-ness" as soon as the Kinect sensor is started (if this observation is incorrect, or there is a workaround, PLEASE let me know). Because of that, I was required to make a special start() method in the Speech manager, which looks like this:
// SpeechManager.cs
/** For use with the Kinect Microphone **/
public void start(KinectManager kinect)
{
// Get the speech recognizer information
RecognizerInfo recogInfo = SpeechRecognitionEngine.InstalledRecognizers().FirstOrDefault();
if (null == recogInfo)
{
Console.WriteLine("Error: No recognizer information found on Kinect");
return;
}
SpeechRecognitionEngine recognizer = new SpeechRecognitionEngine(recogInfo.Id);
// Loads all of the grammars into the recognizer engine
loadSpeechBindings(recognizer);
// Set speech event handler
recognizer.SpeechRecognized += speechRecognized;
using (var s = kinect.getAudioSource().Start() )
{
// Set the input to the Kinect audio stream
recognizer.SetInputToAudioStream(s, new SpeechAudioFormatInfo(EncodingFormat.Pcm, 16000, 16, 1, 32000, 2, null));
// Recognize asycronous speech events
recognizer.RecognizeAsync(RecognizeMode.Multiple);
}
}
For reference, the start() method in the Kinect manager looks like this:
// KinectManager.cs
public bool start()
{
// Code from Microsoft Sample
kinect = (from sensorToCheck in KinectSensor.KinectSensors where sensorToCheck.Status == KinectStatus.Connected select sensorToCheck).FirstOrDefault();
// Fail elegantly if no kinect is detected
if (kinect == null)
{
connected = false;
Console.WriteLine("Couldn't find a Kinect");
return false;
}
// Start listening
kinect.Start();
// Enable listening for all skeletons
kinect.SkeletonStream.Enable();
// Obtain the KinectAudioSource to do audio capture
source = kinect.AudioSource;
source.EchoCancellationMode = EchoCancellationMode.None; // No AEC for this sample
source.AutomaticGainControlEnabled = false; // Important to turn this off for speech recognition
kinect.AllFramesReady += new EventHandler<AllFramesReadyEventArgs>(allFramesReady);
connected = true;
return true;
}
So when I disable motion capture (by having my main() look similar to the first code segment), speech recognition works fine. When I enable motion capture, motion works great but no speech gets recognized. In both cases, keyboard events always work. There are no errors, and through tracing I found out that all the data in the speech manager is initialized correctly... it seems like the speech recognition events just disappear. How can I reorganize this code so that the input modules can work independently? Do I use threading, or just Application.Run() in a different way?
The Microsoft Kinect SDK have several known issues, one of them being that audio is not processed if you begin tracking the skeleton after starting the audio processor. From the known issues:
Audio is not processed if skeleton stream is enabled after starting audio capture
Due to a bug, enabling or disabling the SkeletonStream will stop the AudioSource
stream returned by the Kinect sensor. The following sequence of instructions will
stop the audio stream:
kinectSensor.Start();
kinectSensor.AudioSource.Start(); // --> this will create an audio stream
kinectSensor.SkeletonStream.Enable(); // --> this will stop the audio stream as an undesired side effect
The workaround is to invert the order of the calls or to restart the AudioSource after changing SkeletonStream status.
Workaround #1 (start audio after skeleton):
kinectSensor.Start();
kinectSensor.SkeletonStream.Enable();
kinectSensor.AudioSource.Start();
Workaround #2 (restart audio after skeleton):
kinectSensor.Start();
kinectSensor.AudioSource.Start(); // --> this will create an audio stream
kinectSensor.SkeletonStream.Enable(); // --> this will stop the audio stream as an undesired side effect
kinectSensor.AudioSource.Start(); // --> this will create another audio stream
Resetting the SkeletonStream engine status is an expensive call. It should be made at application startup only, unless the app has specific needs that require turning Skeleton on and off.
I also hope that when you say you're using "version 1" of the SDK, you mean "version 1.6". If you are using anything but 1.5 or 1.6, you are only hurting yourself due to the many changes that were made in 1.5.
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