PosKeyboard 实现(POS for .NET v1.14 SDK 文档)

PosKeyboard 服务对象从 POS 键盘读取键。 POS 键盘可以是辅助键盘,也可能是包含系统键盘上部分或全部键的虚拟键盘。 在 .NET 版的 Microsoft 销售点(POS for .NET)中,POS 键盘 基类PosKeyboardBase

PosKeyboard 服务对象遵循常规输入设备模型:

  • 从 POS 键盘接收到输入时,会将 DataEvent 排入队列。
  • 如果 AutoDisable 属性 为 true,则当 DataEvent 事件排队时,设备会自动禁用自身。 这由 PosKeyboardBase 类自动完成。
  • DataEvent 事件已排入队列,并且 DataEventEnabled 属性为 true 且满足其他事件传递要求时,该事件将传递到应用程序。 PosKeyboardBase 类将自动管理事件传递。
  • 当收集或处理输入时出错,ErrorEvent 事件会排入队列。当 DataEventEnabledtrue 并且满足其他事件传递要求时,该事件将被传递到应用程序。
  • DataCount 属性由 PosKeyboardBase 类维护,可以读取它以获取排队事件数。
  • 所有排队输入都可以通过调用 ClearInput()来删除。

POS 键盘是独占使用的设备:

  • 应用程序在启用设备之前必须声明该设备。
  • 应用程序必须在设备开始读取输入之前声明并启用设备。

本部分包含一个 示例 PosKeyboard 服务对象,该对象生成使用 DataEvents 发送到应用程序的模拟击键。 此示例依赖于 服务对象读取器线程介绍中介绍的线程助手对象。 若要编译此示例,需要包含该主题中的代码。

编写服务对象

  1. Microsoft.PointofServiceMicrosoft.PointOfService.BaseServiceObjectsSystem.Threading 添加 using 指令。

  2. 添加全局属性 PosAssembly

  3. 为项目选择适当的命名空间名称。

  4. 创建派生自 PosKeyboardBase 的服务对象类。

  5. ServiceObject 属性添加到 Service Object 类,使用 DeviceType.PosKeyboard 值作为设备类型。

向示例键盘服务对象添加功能

  1. 创建一个线程帮助程序类 KeyboardThreadingObject,派生自 ServiceObjectThreadHelperService 对象读取线程 部分。

  2. KeyboardThreadingObject 类中实现 ServiceObjectThreadProcedure 方法。 这是将在单独的线程上运行的过程。 在下面的示例代码中,此方法模拟键盘输入。

  3. 此示例类实现名为 SendKey 的方法和另一个名为 ChangePowerState 的方法。 这些方法是受保护成员周围的包装器。 由于它们受到保护,因此无法直接从线程处理对象调用它们。

  4. 重写 PosCommon.Open 方法以指定此服务对象支持的功能并创建新的线程帮助程序对象。

  5. 专门重写 PosCommon.DeviceEnable打开关闭 线程帮助程序。

  6. PosCommon 实现抽象虚拟方法,提供最低功能。

运行应用程序

此示例服务对象可与 POS for .NET 软件开发工具包(SDK)提供的测试应用程序一起运行。

测试服务对象

  1. 启动测试应用程序,然后从键盘下拉列表中选择 SamplePosKeyboard

  2. 打开声明 设备,然后选择带有 DeviceEnabled 复选框的设备以启用该设备。

  3. 选中 DataEventEnabled 框将允许服务对象向应用程序发送单个模拟密钥。 当调用 KeyDown 时,DataEvent 会由 PosKeyboardBase 类自动排队。

  4. 选择“ 自动启用数据事件 ”框后,服务对象可以继续传递字符(两秒)。

  5. 服务对象将发送字符“a”到“z”的模拟键笔划。 之后,将发送 StatusUpdateEvent 事件,指示设备现在处于脱机状态。 当 Properties.PowerState 发生更改时,PosKeyboardBase 类会自动发送此事件。

Example

此示例演示如何开发简单的 PosKeyboard 服务对象。 它支持单独的读取器线程以异步方式将 DataEvents 发送到应用程序。 编译后,可以将服务对象与 POS for .NET SDK 附带的测试应用程序一起执行。

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

using Microsoft.PointOfService;
using Microsoft.PointOfService.BaseServiceObjects;

[assembly: PosAssembly("Service Object Contractors, Inc.")]

namespace SOSamples.Keyboard
{
    [ServiceObject(
            DeviceType.PosKeyboard,
            "SamplePosKeyboard",
            "Sample PosKeyboard Service Object",
            1,
            9)]

    public class SampleKeyboard : PosKeyboardBase
    {
        KeyboardThreadingObject ReadThread = null;

        public SampleKeyboard()
        {
            // DevicePath must be set before Open() is called.
            // In the case of Play and Plug hardware, the
            // POS for .NET Base class will set this value.
            DevicePath = "Sample Keyboard";

            // NOTE: You can test the power notification events
            // sent from this Service Object by selecting the
            // "Power Notify" check box.

            // Let the application know advanced power
            // reporting is supported.
            Properties.CapPowerReporting = PowerReporting.Advanced;
            Properties.CapKeyUp = false;
        }

        ~SampleKeyboard()
        {
            // Code added from previous sections to terminate
            // the read thread started by the thread-helper
            // object.
            if (ReadThread != null)
            {
                ReadThread.CloseThread();
            }

            Dispose(false);
        }

        // Expose the protected KeyDown() method so that it can be
        // called from our threading helper.
        public void SendKey(int key)
        {
            KeyDown(key);
        }

        // Expose the protected PowerState property so it can be
        // changed from the threading helper.
        public void ChangePowerState(PowerState state)
        {
            Properties.PowerState = state;
        }

        #region Override Virtual PosCommon Members
        public override void Open()
        {
            base.Open();

            // Create the reader-thread object.
            ReadThread = new KeyboardThreadingObject(this);
        }

        public override bool DeviceEnabled
        {
            get
            {
                return base.DeviceEnabled;
            }
            set
            {
                if (value != base.DeviceEnabled)
                {
                    base.DeviceEnabled = value;

                    if (value == false)
                    {
                        // Stop the reader thread when the device
                        // is disabled.
                        ReadThread.CloseThread();
                    }
                    else
                    {
                        try
                        {
                            // By enabling the device, start the
                            // reader thread.
                            ReadThread.OpenThread();
                        }
                        catch (Exception e)
                        {
                            base.DeviceEnabled = false;

                            if (e is PosControlException)
                                throw;

                            throw new PosControlException(
                                    "Unable to Enable Device",
                                    ErrorCode.Failure, e);
                        }
                    }
                }
            }
        }
        #endregion Override Virtual PosCommon Members

        #region Implement Abstract PosCommon Members
        private string MyHealthText = "";

        // PosCommon.CheckHealthText.
        public override string CheckHealthText
        {
            get
            {
                // VerifyState(mustBeClaimed,
                // mustBeEnabled).
                VerifyState(false, false);
                return MyHealthText;
            }
        }

        //  PosCommon.CheckHealth.
        public override string CheckHealth(
                        HealthCheckLevel level)
        {
            // Verify that device is open, claimed and enabled.
            VerifyState(true, true);

            // Your code here:
            // Check the health of the device and return a
            // descriptive string.

            // Cache result in the CheckHealthText property.
            MyHealthText = "Ok";
            return MyHealthText;
        }

        // PosCommon.DirectIOData.
        public override DirectIOData DirectIO(
                                int command,
                                int data,
                                object obj)
        {
            // Verify that the device is open.
            VerifyState(false, false);

            return new DirectIOData(data, obj);
        }
        #endregion  Implement Abstract PosCommon Members
    }

    #region Thread Helper Class
    public class KeyboardThreadingObject :
        ServiceObjectThreadHelper, IDisposable
    {
        // This is a helper class which will depend on
        // being able to call back into the actual Service
        // Object to pass along data. However, you cannot
        // keep a strong reference to the Service Object,
        // since that may prevent clean disposal, leaving
        // hardware resources unavailable to other processes.
        // Therefore, you create a weak reference. From this
        // reference, you can get a temporary strong reference,
        // which you can act on and then release.
        WeakReference ServiceObjectReference;

        // The name of the Service Object.
        string ObjectName;

        public KeyboardThreadingObject(SampleKeyboard so)
        {
            ObjectName = GetType().Name;
            ServiceObjectReference = new WeakReference(so);
        }

        // This method will be called during initialization.
        public override void ServiceObjectThreadOpen()
        {
            Logger.Info(ObjectName, "Keyboard Thread Open");
        }

        // This method will be called curing shutdown.
        public override void ServiceObjectThreadClose()
        {
            Logger.Info(ObjectName, "Keyboard Thread Open");
        }

        // Your code used to monitor your device for input should
        // go here. The implementation below generates simulated
        // input as an example.
        public override void ServiceObjectThreadProcedure(
                            AutoResetEvent ThreadStopEvent)
        {
            Logger.Info(ObjectName,
                            "Keyboard Thread Procedure Entered");
            int KeyValue = (int)'a';

            while (true)
            {
                // When this method is called by the
                // ServiceObjectThreadHelper, it is obligated to
                // exit when the event ThreadStopEvent has been
                // set.
                if (ThreadStopEvent.WaitOne(2000, false))
                {
                    break;
                }

                if (KeyValue <= (int) 'z')
                {
                    Logger.Info(ObjectName, "Reader Thread cycling");

                    // Try to get a strong reference to the Service
                    // Object using the weak reference saved when
                    // this helper object was created.
                    SampleKeyboard Keyboard =
                        ServiceObjectReference.Target
                        as SampleKeyboard;

                    // If this fails, that means the Service Object
                    // has already been disposed of - exit the thread.
                    if (Keyboard == null)
                    {
                        break;
                    }

                    if (Keyboard.DataEventEnabled == true)
                    {
                        // Call a method implemented in our Keyboard
                        // class to queue the key stroke.
                        Keyboard.SendKey(KeyValue);

                        // Simulate input by moving through the
                        // alphabet, sending one character at a time.
                        KeyValue++;
                        if (KeyValue >= (int)'z')
                        {
                            // Once you run out of input, simulate a
                            // power state change. Setting the SO's
                            // PowerState property to
                            // PowerState.Offline will cause a
                            // StatusUpdateEvent to be sent to the
                            // application.
                            Keyboard.ChangePowerState(
                                            PowerState.Offline);

                            // Release the strong reference.
                            Keyboard = null;

                            // There is no more work, so exit the
                            // loop.
                            break;
                        }
                    }

                    // Release the strong reference.
                    Keyboard = null;
                }
            }
        }
    }
    #endregion Thread Helper Class
}

编译代码

  • 此示例要求包含 “服务对象读取器线程” 部分中的代码。
  • 必须引用程序集 Microsoft.PointOfServiceMicrosoft.PointOfService.BaseServiceObjects

另请参阅

Tasks

其他资源