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.
Related
I coded with c# in visual studio, windows form application. I want to see pid and vid of a USB when ıt is plugged in. I wrote this code but there is an error in foreach (ManagementObject service in s.Get()). In s.Get() part. It runs in Form1_Load part but it gets stuck in WNDProc.
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if(m.Msg == WM_DEVICECHANGE)
switch ((int)m.WParam)
{
case DBT_DEVICEARRIVAL:
listBox1.Items.Add("New Device Connected");
ManagementObjectSearcher s = new ManagementObjectSearcher("#SELECT * FROM Win32_USBHub");
foreach (ManagementObject service in s.Get())
{
listBox1.Items.Add(service);
}
string[] ports = SerialPort.GetPortNames();
Console.WriteLine("The following serial ports were found:");
foreach (string port in ports)
{
Console.WriteLine(port);
listBox1.Items.Add(port);
}
break;
case DBT_DEVICEREMOVECOMPLETE:
listBox1.Items.Add("Device Removed");
break;
}
The main issue is that the WM_DEVICECHANGE only comes for information you registered, with a few exceptions as can be read in the remarks of RegisterDeviceNotification.
Here are the details what you need to do:
To get the WM_DEVICECHANGE with DBT_DEVICEARRIVAL for devices, you need to call the Win32 API in user32.dll called RegisterDeviceNotification with a correctly filled DEV_BROADCAST_DEVICEINTERFACE_W struct.
If done so correctly you will get WM_DEVICECHANGE messages, which contain the event type (in our case DBT_DEVICEARRIVAL) as described in the Device Management Events, and a pointer to details. The pointer needs to be read as the DEV_BROADCAST_HDR struct , allowing you to recognise if this is indeed the DEV_BROADCAST_DEVICEINTERFACE_W struct. If so this struct will contain a name, which you will need to parse at it contains the VID & PID.
That is quite a lot to process, and it took me a couple of hours to get it right. If you need a quick solution, and skip implementing the horrible details, add the NuGet package Dapplo.Windows.Messages (VID & PID are available with 0.9.7 and later) to your project. Use the following code only once, otherwise your code will be called multiple times, there is no need to do this from a Window but it must be from a Windows Forms or WPF application:
var deviceNotificationSubscription = DeviceNotification
.OnDeviceArrival()
.Subscribe(deviceInterfaceChangeInfo => {
// Your code goes here, and will be automatically called
var vid = deviceInterfaceChangeInfo.Device.VendorId;
var pid = deviceInterfaceChangeInfo.Device.ProductId;
});
My library highly depend on System.Reactive, I won't go into details here, which allows a more functional approach to your application. You can stop receiving the events by calling deviceNotificationSubscription.Dispose(); The library creates it's own hidden message window to receive the window messages, so you can even continue receiving the information in the background.
The Device property of the DeviceInterfaceChangeInfo has the DevBroadcastDeviceInterface struct, which contains the original Win32 information, but additionally has some higher level properties like:
a friendly name, which is retrieved from the registry
device type like USB, HID etc including an IsUSB
vendor ID
product ID
a DeviceInterfaceClass enum for easier code access to the class
a generated URL to get more information on the device
Let me know if this works and helps here by and if you have any questions raise an issue on my Dapplo.Windows GitHub project! There is a lot more in this library but unfortunately most documentation still needs writing.
I just started to take a look at xamarin and now I want to scan for bluetooth-devices. Therefor I use the following code:
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.DefaultAdapter;
bluetoothAdapter.StartDiscovery();
And I have the following class for getting the result:
[BroadcastReceiver]
[IntentFilter(new [] {BluetoothAdapter.ActionDiscoveryFinished})]
public class BluetoothReceiver : BroadcastReceiver
{
public BluetoothReceiver()
{
}
public override void OnReceive(Context context, Intent intent)
{
if (BluetoothAdapter.ActionDiscoveryFinished.Equals(intent.Action))
{
}
}
}
I've also set the permissions for my app to BLUETOOTH and BLUETOOTH_ADMIN. Everything just works fine and the OnReceive-Method is called correctly. My problem now is: How do I get the found devices from the parameters of the OnReceive-Method?
ACTION_DISCOVERY_FINISHED doesn't tell you anything other than the discovery action has finished. https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#ACTION_DISCOVERY_FINISHED
If you wanted to grab devices from the scan, you should read what startDiscovery() has to say regarding finding devices:
The discovery process usually involves an inquiry scan of about 12 seconds, followed by a page scan of each new device to retrieve its Bluetooth name.
This is an asynchronous call, it will return immediately. Register for ACTION_DISCOVERY_STARTED and ACTION_DISCOVERY_FINISHED intents to determine exactly when the discovery starts and completes. Register for ACTION_FOUND to be notified as remote Bluetooth devices are found.
https://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startDiscovery()
Thus you should use ACTION_FOUND and parse the EXTRA_DEVICE for devices:
Broadcast Action: Remote device discovered.
Sent when a remote device is found during discovery.
Always contains the extra fields EXTRA_DEVICE and EXTRA_CLASS. Can contain the extra fields EXTRA_NAME and/or EXTRA_RSSI if they are available.
https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#ACTION_FOUND
In sequence of events, you would do the following:
ACTION_DISCOVERY_STARTED - Which will start discovery
ACTION_FOUND - Which will find a device
ACTION_DISCOVERY_FINISHED - Which will end discovery
As for beginner, I would recommend looking into cross-platform libraries, e.g. https://github.com/xabre/xamarin-bluetooth-le, https://github.com/aritchie/bluetoothle
This not only abstracts the platform-specific stuff, offers a simple interface to work with, but also give you multi-platform support out of the box.
I understand that this might be not the answer you're looking for, but in the end, this is what the main advantage of Xamarin is about - write once, run anywhere, etc.
I am writing a C# WPF program which sends text messages to another program's window. I have a macro program as part of my keyboard drivers (Logitech g15) which already does this, though it does not send keystrokes directly to the process, but to the currently focused window. It works well but i need to be able to send inputs from my program as well. There are other people using the process so the input text messages from my program needs to be fast enough so that my text does not interfere with their input.
The problem is that when I try to do this with a c# program I get too much delay. The macro program (Logitech G-Series Profiler) sends a command instantly. I have tried the following three commands for sending messages to process. (Listed by order of slowest to fastest)
SetForegroundWindow(_hWnd);
SendKeys.SendWait("{Enter}This is a keystroke input.{Enter}");
It is probably in the name, but this performs the command so slowly that I can actually follow with my eyes the text as it is input letter by letter. I have tried using the “SendKeys.Send” method but I get an error saying: “SendKeys cannot run inside this application because the application is not handling Windows messages.”
PostMessage((IntPtr)_hWnd, (uint)WMessages.WM_KEYUP, (int)key, (int)key);
PostMessage is a bit faster but still not fast enough for the purpose of my program. Besides the method returns before the message has been read by the process, which means two sequential PostMessage calls may not send sequential messages.
SendMessage(_hWnd, 0x100, (int) VKeys.VK_2, (int) VKeys.VK_2);
This is faster than the PostMessage but not nearly as fast as the macro program from Logitech. Also, the receiving program handles the input strangely, apparently not treating it the same way it does "genuine" input from the keyboard.
SetForegroundWindow(_hWnd);
const string text = "This is a keystroke input.";
IInputElement target = Keyboard.FocusedElement;
IInputElement target = InputManager.Current.PrimaryKeyboardDevice.FocusedElement;
var routedEvent = TextCompositionManager.TextInputEvent;
target.RaiseEvent(new TextCompositionEventArgs(InputManager.Current.PrimaryKeyboardDevice, new TextComposition(InputManager.Current, target, text)) { RoutedEvent = routedEvent });
This is the last thing I have tried. It seems instant with the way the text is sent to a process. However, I have only been able to send this to my own program since Keyboard.FocusedElement returns null when I have another program set as foreground window.
If someone can tell me how to get an IInputElement of another window I would sure like to know. Alternatively, if someone has a suggestion for a better method of sending input, I would dearly like to hear it.
Specs: Windows 7, 64bit
Visual Studio 2010, Framework 4
First of all, are you intentionally using WM_KEYDOWN (0x0100) instead of WM_KEYUP (0x0101) in your SendMessage example? This would just press the keys, and never release them, so the application would not process them properly.
Another way worth trying would be to send WM_SETTEXT, assuming the control interprets it correctly (like edit controls or combo boxes).
A last option would be to use SendInput which synthesizes keyboard and mouse input on a very low level, but similarly to you keyboard's macro program, this requires you to activate the correct window and set the focus, which can be quite painful.
Depending on your other's program window type, you could use UI Automation. See this example here:
Add Content to a Text Box Using UI Automation
The only good software I know which can decelerate and accelerate the playback of a YouTube video in any browser without first downloading it (because that would be cumbersome), is Enounce MySpeed.
Unfortunately, this software is not free, and my trial version ran out. I was playing around with its registry settings and noticed a few keys:
ProgramsToHook: iexplore.exe;firefox.exe;plugin-container.exe;chrome.exe;safari.exe;opera.exe;maxthon.exe;feeddemon.exe;realplay.exe;flvplayer.exe;flv player.exe;flock.exe;adobe media player.exe
UseFlashAdapter: 1
LLModules: ole32.dll;nspr4.dll;chrome.exe;realplay.exe;objb3201.dll;oleaut32.dll;rpflashplayer.dll
ModulesToIntercept: flash10*;flash9*;npswf32.dll;gcswf32.dll;fldbg10*;flashplayer.3.1.1k.ocx;adobe media player.exe
Based on the names and values of these registry keys, I'm guessing the MySpeed software hooks some function(s) in the listed modules (but modules are or aren't the same as DLLs?..) and does so for each process listed in ProgramsToHook. This is what I don't understand. What is the concept of the MySpeed software. Obviously it's hooking something, but I'm not too familiar with the intricacies of Windows hooks so I came to ask you experts. I'm thinking if I can understand how this hook process works, I can make my own version of the software using EasyHook, which is a fantastic .NET library to perform user-mode and kernel-mode hooks.
I thought that Windows user-mode hooking goes something like this. You choose one function in one DLL, and you intercept that function (a.k.a hook) in one process you want. If you want to hook the DLL in multiple processes, you just have to repeat the procedure for each process.
And then kernel-mode hooking is just choosing one function in one DLL and intercepting that function in every process that calls it (hence kernel-mode). But surely there are tons of ways to hook; I'm not too sure on whats the difference between these two hooks and DLL injection either.
So the point is, I'd like to know how MySpeed works. What is their hooking concept? If I can know this then I can make such a software in .NET!
Thanks in advance.
I can't provide you with an accurate explanation as I don't know the API calls or capabilites, but it goes something like this:
You app looks for iexplore.exe where it intercepts calls to certain modules. The module is mainly flash player. Flash has support for playing the video slower so you modify the call from iexplore.exe (JavaScript play button on webpage) or make an additional call to set playback speed.
What you need to do:
Use this tool to check what is actually happening: http://www.nektra.com/products/deviare-api-hook-windows/
Learn how to ask Flash Player to slow down a video (probably in Flash API docs). One Simple approach could be to see what MySpeed is actually doing using the Deviare API hook tool.
Write a program that replicates this procedure. It involves intercepting messages sent from one handle (iexplore.exe) to another (flash .dll). This can't be done externally, it has to be done internally, so this may be of help: http://www.codeproject.com/KB/threads/winspy.aspx
On hooks: http://msdn.microsoft.com/en-gb/library/ms644960.aspx
I don't think many people has done this in C#, so it could offer a challenge. I would though be interested in the progress (obstacles) if you have a blog or something to share the gory details on. :)
EDIT: The Deviare API Hook software seems not only to spy on calls, but also allow you to intercept them. So its a all-in-one package for your needs. :)
EDIT2: Relevant question: How do I intercept messages being sent to a window?
The key to speeding up or slowing down a video is to convince multimedia players that your computer is slower or faster than it really is. This can be accomplished hooking timeGetTime().
This is an extremely easy C# code to accomplish it:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Nektra.Deviare2;
namespace DeviareTest
{
public partial class Form1 : Form
{
private int nSpeed;
private uint nTime;
private NktSpyMgr _spyMgr;
public Form1()
{
InitializeComponent();
_spyMgr = new NktSpyMgr();
_spyMgr.Initialize();
_spyMgr.OnFunctionCalled += new DNktSpyMgrEvents_OnFunctionCalledEventHandler(OnFunctionCalled);
}
private void Form1_Load(object sender, EventArgs e)
{
NktHook hook = _spyMgr.CreateHook("WINMM.dll!timeGetTime", (int)(eNktHookFlags.flgOnlyPostCall));
hook.Hook(true);
bool bProcessFound = false;
NktProcessesEnum enumProcess = _spyMgr.Processes();
NktProcess tempProcess = enumProcess.First();
while (tempProcess != null)
{
if (tempProcess.Name.Equals("iexplore.exe", StringComparison.InvariantCultureIgnoreCase) && tempProcess.PlatformBits == 32)
{
hook.Attach(tempProcess, true);
bProcessFound = true;
}
tempProcess = enumProcess.Next();
}
if(!bProcessFound)
{
MessageBox.Show("Please run \"iexplore.exe\" before!", "Error");
Environment.Exit(0);
}
}
private void OnFunctionCalled(NktHook hook, NktProcess process, NktHookCallInfo hookCallInfo)
{
nTime++;
if (nSpeed==-2)
hookCallInfo.Result().LongVal = hookCallInfo.Result().LongVal - (int)(nTime * 0.2);
else if(nSpeed==2)
hookCallInfo.Result().LongVal = hookCallInfo.Result().LongVal + (int)(nTime * 3);
}
private void SlowButton_CheckedChanged(object sender, EventArgs e)
{
nSpeed = -2;
}
private void FastButton_CheckedChanged(object sender, EventArgs e)
{
nSpeed = 2;
}
}
}
I just published an article with a code example showing how to do this with the Deviare hooking engine. The sample code only works with the video part (not audio) and it is available here.
Youtube now has an html5 player with playback speed controls.
All you have to do is enable html5 here http://www.youtube.com/html5
Only some of the videos support the html5 player yet, though.
Hope this helps.
The key to speeding up or slowing down a video is to convince multimedia players that your computer is slower or faster than it really is
manipulating the system time will be a VERY dangerous and idiotic thing to do - not only will you break user-mode threadslices and hence have a serious impact on system-performance but you also will break many logging-functionalities and even user-mode reflectors which control KM-drivers ... this could both crash and physically harm (!) your system because modern hardware is programmable, given the correct (& proprietary, of course) set of func-calls and such. I would highly advise to NOT do reproduce this, even a few AV-apps will intercept this because of its dangerous nature.
But you're somewhat lucky : the kernel uses its own time, synced to hardware so windows itself COULD remain stable for a limited amount of time.
I think you should get back to the drawing-board, manipulating essential structures of your operating-system certainly is not the right way to accomplish your goal.
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();
}
}