因此,我在Windows Forms上遇到了这样的问题,但并非与您描述的问题完全相同。
我知道我的解决方案不是一个为您提供预编码的易用性解决方案,但我认为通过一些小的修改,我几年前克服的障碍可能对您有所帮助。如果您认为我的解决方案可以帮助您,我可以发送给您任何缺失的部分。
我创建了一个利用条形码扫描器的库存管理系统,并决定通过引入一些C++类来实现处理设备输入的能力,而不需要使用诸如文本框之类的输入控件。我需要应用程序能够处理条形码输入并做出决策,而不需要任何额外的用户交互或要求。只要扫描和执行即可。从键盘/HID设备实时获取输入值是我认为该解决方案适合您问题的原因之一。
在测试我编写的应用程序时,我能够在全屏游戏中使用条形码扫描器,就像在Windows Forms库存应用程序中一样。这个功能应该在控制台环境中也同样有效,因为当它们在后台运行时,控制台应用程序不会停止。您甚至可以将其设置为NT AUTHORITY,防止其在作为服务运行时显示到桌面,它仍然会继续运行。
我的做法是使用Win32API反射设备,并通过与应用程序指定的设备匹配,为该特定设备建立监听器。
您可以使用控制台应用程序触发指纹传感器,方法是将控制台应用程序作为本地服务帐户运行或以编程方式获取所需的授权(这将允许您在没有UAC阻碍的情况下以提升的权限运行它),然后在您的Metro应用程序中使用此功能,以读取设备发送的输入。
以下是一些代码文件,用于描述我所描述的内容,并已修改为特定于我的条形码扫描器功能。
同样,请私下联系我,如果您想查看任何缺失的部分。
附注:从技术上讲,这可以用作拦截键等操作的黑客工具,因此我将放置一个免责声明,由您自行决定使用,我对任何愚蠢行为造成的后果不负责。
BarcodeScannerListenerInteropHelper.h:
#include <winuser.h>
BEGIN_INTEROP_NAMESPACE
using namespace System;
using namespace System::Collections::Generic;
using namespace HFSLIB::Barcode;
using namespace HFSLIB::Barcode::Interop;
using namespace HFSLIB::Barcode::Infrastructure::BarcodeScannerListener;
public ref class BarcodeScannerListenerInteropHelper
{
public:
Dictionary<IntPtr, BarcodeScannerDeviceInfo^>^ InitializeBarcodeScannerDeviceHandles(
IEnumerable<String^>^ hardwareIds);
void HookRawInput(IntPtr hwnd);
void GetRawInputInfo(
IntPtr rawInputHeader,
IntPtr% deviceHandle,
bool% handled,
String^% buffer);
private:
static BarcodeScannerDeviceType GetBarcodeScannerDeviceType(DWORD rawInputType);
};
END_INTEROP_NAMESPACE
BarcodeScannerListenerInteropHelper.cpp:
#include "BarcodeScannerListenerInteropHelper.h"
using namespace System::ComponentModel;
BEGIN_INTEROP_NAMESPACE
void BarcodeScannerListenerInteropHelper::GetRawInputInfo(
IntPtr rawInputHeader,
IntPtr% deviceHandle,
bool% handled,
String^% buffer)
{
UINT cbSize;
HRAWINPUT hRawInput;
hRawInput = (HRAWINPUT)rawInputHeader.ToPointer();
if (GetRawInputData(hRawInput, RID_INPUT, NULL, &cbSize, sizeof(RAWINPUTHEADER)) == 0)
{
RAWINPUT* raw;
raw = (RAWINPUT*)malloc(cbSize);
if (GetRawInputData(hRawInput, RID_INPUT, raw, &cbSize, sizeof(RAWINPUTHEADER)) == cbSize)
{
deviceHandle = IntPtr(raw->header.hDevice);
handled = raw->header.dwType == RIM_TYPEKEYBOARD &&
raw->data.keyboard.Message == WM_KEYDOWN;
if (handled)
{
BYTE state[256];
GetKeyState(0);
if (GetKeyboardState(state))
{
WCHAR unmanagedBuffer[64];
if (ToUnicode(raw->data.keyboard.VKey,
raw->data.keyboard.MakeCode,
state,
unmanagedBuffer,
64,
0) > 0)
{
buffer = gcnew String(unmanagedBuffer);
}
}
}
}
free(raw);
}
}
void BarcodeScannerListenerInteropHelper::HookRawInput(IntPtr hwnd)
{
RAWINPUTDEVICE rid[1];
rid[0].dwFlags = 0;
rid[0].hwndTarget = (HWND)hwnd.ToPointer();
rid[0].usUsage = 0x06;
rid[0].usUsagePage = 0x01;
if (!RegisterRawInputDevices(rid, 1, sizeof(RAWINPUTDEVICE)))
{
InvalidOperationException^ e;
e = gcnew InvalidOperationException(
"The barcode scanner listener could not register for raw input devices.",
gcnew Win32Exception());
throw e;
}
}
Dictionary<IntPtr, BarcodeScannerDeviceInfo^>^ BarcodeScannerListenerInteropHelper::InitializeBarcodeScannerDeviceHandles(IEnumerable<String^>^ hardwareIds)
{
Dictionary<IntPtr, BarcodeScannerDeviceInfo^>^ devices;
UINT uiNumDevices;
UINT cbSize;
devices = gcnew Dictionary<IntPtr, BarcodeScannerDeviceInfo^>();
uiNumDevices = 0;
cbSize = sizeof(RAWINPUTDEVICELIST);
if (GetRawInputDeviceList(NULL, &uiNumDevices, cbSize) != -1)
{
PRAWINPUTDEVICELIST pRawInputDeviceList;
if (pRawInputDeviceList = (PRAWINPUTDEVICELIST)malloc(cbSize * uiNumDevices))
{
if (GetRawInputDeviceList(pRawInputDeviceList, &uiNumDevices, cbSize) != -1)
{
for (UINT i = 0; i < uiNumDevices; ++i)
{
UINT pcbSize;
RAWINPUTDEVICELIST rid;
rid = pRawInputDeviceList[i];
if (GetRawInputDeviceInfo(rid.hDevice, RIDI_DEVICENAME, NULL, &pcbSize) >= 0 &&
pcbSize > 0)
{
WCHAR* deviceName;
deviceName = (WCHAR*)malloc(sizeof(WCHAR) * (pcbSize + 1));
if (GetRawInputDeviceInfo(rid.hDevice, RIDI_DEVICENAME, deviceName, &pcbSize) >= 0)
{
bool add;
IntPtr deviceHandle;
BarcodeScannerDeviceInfo^ info;
String^ managedDeviceName;
add = false;
deviceHandle = IntPtr(rid.hDevice);
managedDeviceName = gcnew String(deviceName);
for each (String^ hardwareId in hardwareIds)
{
if (managedDeviceName->IndexOf(hardwareId, StringComparison::OrdinalIgnoreCase) >= 0)
{
add = true;
break;
}
}
if (add)
{
info = gcnew BarcodeScannerDeviceInfo(
managedDeviceName,
BarcodeScannerListenerInteropHelper::GetBarcodeScannerDeviceType(rid.dwType),
deviceHandle);
devices->Add(deviceHandle, info);
}
}
free(deviceName);
}
}
}
free(pRawInputDeviceList);
}
}
return devices;
}
BarcodeScannerDeviceType BarcodeScannerListenerInteropHelper::GetBarcodeScannerDeviceType(DWORD rawInputType)
{
BarcodeScannerDeviceType type;
switch (rawInputType)
{
case RIM_TYPEHID:
type = BarcodeScannerDeviceType::HumanInterfaceDevice;
break;
case RIM_TYPEKEYBOARD:
type = BarcodeScannerDeviceType::Keyboard;
break;
default:
type = BarcodeScannerDeviceType::Unknown;
break;
}
return type;
}
END_INTEROP_NAMESPACE
BarcodeScannerListener.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Permissions;
using System.Text;
using System.Windows.Forms;
using HFSLIB.Barcode.Infrastructure.BarcodeScannerListener;
using HFSLIB.Barcode.Interop;
namespace HFSLIB.Barcode
{
public class BarcodeScannerListener : NativeWindow
{
private Dictionary<IntPtr, BarcodeScannerDeviceInfo> devices;
private BarcodeScannerKeyDownMessageFilter filter;
private StringBuilder keystrokeBuffer;
private BarcodeScannerListenerInteropHelper interopHelper =
new BarcodeScannerListenerInteropHelper();
public event EventHandler BarcodeScanned;
public void Attach(Form form)
{
IntPtr hwnd;
if (form == null)
{
throw new ArgumentNullException("form");
}
hwnd = form.Handle;
this.keystrokeBuffer = new StringBuilder();
this.InitializeBarcodeScannerDeviceHandles();
this.interopHelper.HookRawInput(hwnd);
this.HookHandleEvents(form);
this.AssignHandle(hwnd);
this.filter = new BarcodeScannerKeyDownMessageFilter();
Application.AddMessageFilter(this.filter);
}
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case NativeMethods.WM_INPUT:
if (this.ProcessRawInputMessage(m.LParam))
{
this.filter.FilterNext = true;
}
break;
}
base.WndProc(ref m);
}
private void FireBarcodeScanned(BarcodeScannerDeviceInfo deviceInfo)
{
string barcode;
EventHandler handler;
barcode = this.keystrokeBuffer.ToString();
if (barcode != null && barcode.Length > 0)
{
handler = this.BarcodeScanned;
this.keystrokeBuffer = new StringBuilder();
if (handler != null)
{
handler(this, new BarcodeScannedEventArgs(barcode, deviceInfo));
}
}
}
private void HookHandleEvents(Form form)
{
form.HandleCreated += this.OnHandleCreated;
form.HandleDestroyed += this.OnHandleDestroyed;
}
private void InitializeBarcodeScannerDeviceHandles()
{
BarcodeScannerListenerConfigurationSection config;
BarcodeScannerListenerConfigurationElementCollection hardwareIdsConfig;
IEnumerable<string> hardwareIds;
config = BarcodeScannerListenerConfigurationSection.GetConfiguration();
hardwareIdsConfig = config.HardwareIds;
hardwareIds = from hardwareIdConfig in hardwareIdsConfig.Cast<BarcodeScannerListenerConfigurationElement>()
select hardwareIdConfig.Id;
this.devices = this.interopHelper.InitializeBarcodeScannerDeviceHandles(hardwareIds);
}
private void OnHandleCreated(object sender, EventArgs e)
{
this.AssignHandle(((Form)sender).Handle);
}
private void OnHandleDestroyed(object sender, EventArgs e)
{
this.ReleaseHandle();
}
private bool ProcessRawInputMessage(IntPtr rawInputHeader)
{
BarcodeScannerDeviceInfo deviceInfo;
bool handled;
bool keystroke;
string localBuffer;
IntPtr rawInputDeviceHandle;
handled = false;
keystroke = false;
localBuffer = string.Empty;
rawInputDeviceHandle = IntPtr.Zero;
this.interopHelper.GetRawInputInfo(
rawInputHeader,
ref rawInputDeviceHandle,
ref keystroke,
ref localBuffer);
if (this.devices.TryGetValue(rawInputDeviceHandle, out deviceInfo) && keystroke)
{
handled = true;
if (localBuffer.Length == 1 && localBuffer[0] == 0xA)
{
this.FireBarcodeScanned(deviceInfo);
}
else
{
this.keystrokeBuffer.Append(localBuffer);
}
}
return handled;
}
}
}