共用方式為


PosKeyboard Implementation (POS for .NET v1.14 SDK 文件)

PosKeyboard 服務物件會讀取 POS 鍵盤上的按鍵。 POS 鍵盤可以是輔助鍵盤,也可能是包含系統鍵盤部分或全部按鍵的虛擬鍵盤。 在 Microsoft Point of Service for .NET(POS for .NET)中,POS 鍵盤 的基底 類別為 PosKeyboardBase

PosKeyboard 服務物件遵循一般輸入裝置模型:

  • 當從 POS 鍵盤接收到輸入時,會排隊一個 DataEvent
  • 如果 AutoDisable 屬性為 true,當 DataEvent 事件被排隊時,裝置會自動停用。 這是由 PosKeyboardBase 類別自動執行的。
  • DataEventEnabled 屬性為且其他事件傳遞需求符合時,將送達一個佇列中的 DataEvent 事件給應用程式。 PosKeyboardBase 類別會自動管理事件傳遞。
  • 若在收集或處理輸入時發生錯誤,則將 ErrorEvent 事件排隊,當 DataEventEnabled 設為 true 且符合其他事件傳遞需求時,該事件會送達給應用程式。
  • PosKeyboardBase 類別維護的 DataCount 屬性可讀取以取得排隊事件數量。
  • 所有排隊輸入皆可透過呼叫 ClearInput() 刪除。

POS 鍵盤是專用裝置:

  • 應用程式必須先取得該裝置的權利,才能啟用。
  • 應用程式必須在裝置開始讀取輸入前先宣稱並啟用該裝置。

本節包含一個範例 PosKeyboard 服務物件,能產生模擬按鍵,並透過 DataEvents 傳送給應用程式。 此範例依賴於 《介紹服務物件讀取線程》中所呈現的線程輔助物件。 要編譯這個範例,你需要包含該主題的程式碼。

撰寫服務物件

  1. 新增對 Microsoft.PointofServiceMicrosoft.PointOfService.BaseServiceObjectsSystem.Threading 的使用指令。

  2. 新增全域屬性 PosAssembly

  3. 為您的專案選擇合適的命名空間名稱。

  4. 建立一個由 PosKeyboardBase 衍生的服務物件類別。

  5. ServiceObject 屬性新增至您的服務物件類別中,並使用 DeviceType.PosKeyboard 作為裝置類型。

若要為服務物件的範例鍵盤新增功能

  1. 建立一個執行緒輔助類別 KeyboardThreadingObject,源自服務物件讀取執行緒區段的 ServiceObjectThreadHelper

  2. KeyboardThreadingObject 類別中實作 ServiceObjectThreadProcedure 方法。 這是會在另一個執行緒上執行的程序。 在下方範例程式碼中,此方法模擬鍵盤輸入。

  3. 此範例類別實作了一個名為 SendKey 的方法,以及另一個名為 ChangePowerState 的方法。 這些方法是包裝在受保護成員外部的。 由於這些資料受到保護,無法直接從執行緒物件呼叫。

  4. 覆寫 PosCommon.Open 方法,指定此服務物件所支援的功能,並建立新的執行緒輔助物件。

  5. 專門覆寫 PosCommon.DeviceEnable 以便特定用於開啟關閉 執行緒輔助器。

  6. 實作 PosCommon 的抽象虛擬方法,提供最小功能。

執行應用程式

此範例服務物件可與隨 POS for .NET 軟體開發套件(SDK)提供的測試應用程式同時執行。

測試服務物件

  1. 啟動測試應用程式,並從鍵盤下拉選單中選擇 SamplePosKeyboard

  2. 開啟認領該裝置,然後勾選DeviceEnabled以啟用該裝置。

  3. 勾選 DataEventEnabled 方框後,服務物件可將單一模擬金鑰傳送給應用程式。 PosKeyboardBase 類別在呼叫 KeyDown 時會自動地將 DataEvent 加入佇列。

  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 這兩個組件。

另請參閱

任務

其他資源