使用 .NET Compact Framework 的條碼掃描器

適用於:
以 Windows Mobile 2003 為基礎的 Pocket PC
Microsoft Visual Studio .NET 2003
Microsoft .NET Compact Framework 1.0 版

摘要:學習如何讓您的應用程式以一般方式使用條碼掃描器,不受到應用裝置以及條碼掃描器類型的限制。採用「外觀」和「工廠」設計樣式的實作不僅支援多個條碼掃描器,還可讓您輕鬆加入其他條碼掃描器的支援。在有關條碼掃描器和條碼掃描器樣式的簡短討論之後,會有一份以 C# 撰寫的下載程式碼範例,示範樣式和這些技術的用途。(此文章包含連至英文網頁的連結,列印共 20 頁)

請從 Microsoft 下載中心下載 Barcode Scanners NETCF.msi

目錄

簡介
條碼
條碼掃描器
條碼掃描器樣式
條碼掃描器範例
程式碼逐步解說
部署
支援額外的條碼掃描器
結論

簡介

專業人員會在各商業場合中使用到條碼掃描器,主要應用範圍有運輸、倉儲、程式庫及實驗室等後勤應用程式。依商品編號 (甚或是唯一的序號) 從製造乃至顧客處追蹤產品去向,有很大的好處,例如產品送回維修時可以派上用場。這項技術能在許多點上擷取資訊,因此非常具有成本效率,專業人員可以輕鬆地收集詳細資訊並加以儲存,供日後分析和決策支援之用。

許多傳統條碼應用程式都是行動式的,顯然適合與 Pocket PC 這類的行動裝置搭配使用,因此各家供應商推出了五花八門的條碼方案。許多整合式裝置都內建有條碼掃描器,而最近的方案卻使用無線技術 (例如藍芽),將條碼掃描器和無線裝置分開。直接從行動裝置使用條碼掃描器顯然有其必要性,因此許多供應商又各自推出了軟體開發套件 (SDK)。許多大型供應商甚至提供立即可用的開發套件,供最新工具使用 (為 .NET Compact Framework 提供受讀取管理的 API);因此,許多企業方案都已採用這些程式庫來整合條碼掃描器和商務方案。

在任何要長久使用的企業方案中,把商務邏輯的和技術基礎結構分開實作是比較理想的作法。典型的例子是條碼掃描器的應用,它們經常用於許多後勤方案中。然而,目前應用程式存取條碼掃描器的方式尚未有通用的標準,因此大部分的情況都是針對特定條碼掃描器,甚至是特定裝置實作。這樣的實作很可能在第一個專案中可行一段時間,到了更換裝置時問題就浮現了。要解決這個問題,我們可以利用抽象層,把條碼掃描器的使用和在不同裝置上的實際實作分開。這樣一來,需要更換舊裝置時,開發人員只需要更新應用程式,就可以支援新裝置和條碼掃描器了。使用抽象層還有另一個好處,應用程式可以同時支援新舊裝置,以便裝置間能夠順利進行轉換。

如前所述,本文將討論此類抽象層的樣式。本文中的 < 下載程式碼範例>將示範這個理論。

條碼

最原始的條碼問世至今已經有 50 年以上,並在大約 40 年前應用在商業上。每個符號中條紋和空格的群組方式都代表一個特定的 ASCII 字元。這些群組的解譯是根據一組特定的規則,稱為「符號表示」。目前使用中的符號表示有 400 多種。

有些條碼符號表示已成為識別特定項目的標準。[表 1] 中有一些範例。

[表 1] 既定標準以及所代表的條碼符號

既定標準 代表項目 條碼符號
UPC-A 或 UPC-E 要在美加地區銷售的項目 UPC/EAN
EAN-8 或 EAN-13 要在全球銷售的項目 UPC/EAN
ISBN、ISSN 和 Booklan 書籍和期刊 EAN-13 及 UPC/EAN
UCC-128、EAN-128 或 SSCC-18 貨物標籤 Code 128
SCC-14、EAN-14 貨物標籤 Interleaved 2 of 5 或 Code 128
SSCC-18 貨物標籤 Code 128
SISAC 或 SICI 代碼 期刊流水號 Code 128
MICR 銀行支票 MICR E-13B 或 CMC-7

幾乎所有的人都接觸過 EAN-13 條碼符號表示,它應用在書籍和期刊上。EAN 是「歐洲商品編碼」(European Article Numbering) 系統 (在日本又稱為 JAN) 的首字母縮略字,相當於是歐洲的一般產品代碼 (UPC)。EAN-13 條碼的大小需求和 UPC 相同,其編碼配置和 UPC 相似。EAN-13 條碼由 13 個數字組成,這 13 個數字包含下列部分:前兩個或前三個數字是國家代碼、接下來的五到七個數字是製造商代碼、再來的三到五個數字是產品代碼,最後一個數字是總和檢查碼。國際標準書號 (ISBN) 或 Booklan 條碼是一種 EAN-13 符號,也就是 ISBN 的前九個數字前面加上數字 978 及額外的總和檢查碼。

條碼掃描器

基本上,Pocket PC 有三種不同類型的條碼掃描器:

  • 內建型
  • 無線型
  • 擴充卡

內建型掃描器可能是最安全的方案,因為這類裝置也大多堅固耐用,像是 Symbol 的 PPT 8800 系列 和 Intermec 的 700 系列。內建型掃描器非常堅固,但也是最沒有彈性的方式,因為條碼掃描器無法在各裝置間共用。

無線型條碼掃描器的最佳代表就是 Baracoda 的 BaracodaPencil。BaracodaPencil 使用藍芽與 Pocket PC 通訊,甚至可以做為 Pocket PC 手寫筆使用。當然,也有完整大小的無線型條碼掃描器,像是 Metrologic 的 Voyager BT。(您可透過 3 D 展示進一步瞭解這項產品)。這些裝置類型都具有下列優點:它們可以在不同的 Pocket PC 間共用。但是,因為在掃描條碼時通常需要伴隨其他資料輸入,要同時管理兩個裝置可能會有問題。

說到擴充卡條碼掃描器,目前有許多不同類型的卡片標準。CompactFlash (CF) 卡在許多 Pocket PC 都有支援,因此非常受歡迎。其他的類型有 PC 卡和安全數位 (SD) 卡。例如, 安全數位掃描卡 3E 就是相當令人期待的選項。它又小 (1.14 英吋 x 1.14 英吋 x 0.55 英吋) 又輕 (0.26 盎司),可搭配大多數的新型 Pocket PC。雖然非常具有彈性,但使用擴充卡條碼掃描器仍有風險,它們不適合太粗心大意的動作也不適合在克難的環境下使用。

另一種使用實體條碼掃描器的方式,就是使用數位相機翻拍條碼,然後再使用軟體解譯條碼。Pocket PC 的商業 (或免費) 方案不多,但是因為數相機可提昇其解析度,所以將來數位相機可能會是令人期待的選項。由於許多 Smartphone 也配有數位相機,一般的 .NET Compact Framework 方案也可支援 Smartphone。

條碼掃描器樣式

條碼掃描器樣式的目的,在於將應用程式使用條碼掃描器,以及在特定裝置上實際操作條碼掃描器這兩件事情分開處理。

這種樣式融合了兩種常見的設計樣式: 外觀樣式 工廠樣式

樣式的類別圖表如 [圖 1] 所示。

Aa446489.barcode_scanners_netcf_01(zh-tw,MSDN.10).gif

[圖 1] 條碼掃描器樣式

一般抽象條碼掃描器有兩種類別:工廠基底類別 BarcodeScannerFactory 及條碼掃描器基底類別 BarcodeScanner。特定的條碼掃描器類別 (例如 Symbol 或 Intermec) 會繼承這些類別。主要的外觀類別 BarcodeScannerFacade決定程式碼要在哪個裝置上執行。外觀類別也負責傳回正確類型的條碼掃描器物件。用戶端程式碼 (通常在表單中) 會呼叫外觀類別 BarcodeScannerFacade 上的靜態方法 GetBarcodeScanner,取得工廠執行個體 (視執行程式碼的裝置而定)。接著外觀類別就會呼叫該工廠上的GetBarcodeScanner 方法,取得正確條碼掃描器的執行個體。

樣式的其中一個重點就是實作 BarcodeScan 事件,此事件在進行新掃描時引發。這個事件本身可能很簡單 (與接下來的範例非常相似),但我們需要思考一下事件引數。如前所述,對於每個掃描,決定應用程式需要何種資訊是很重要的。只要將掃描的資料儲存為文字字串就夠了嗎?或者,應用程式是否支援一種以上的條碼格式,因此事件需要傳遞有關條碼所符合之標準的資訊 (例如,EAN-13 之於 ISBN 條碼)。雖然並非所有的掃描器都支援所有需要的資訊,這些掃描器會改為提供靜態資訊。例如,如果掃描器無法傳遞有關條碼標準的資訊,標準就必須硬式編碼到傳回的事件引數中。

樣式實作目前僅支援在 Symbol 和 Intermec 這兩種裝置上使用條碼掃描器。樣式也僅支援內建在個別裝置中的條碼掃描器。外觀類別決定要使用何種條碼掃描器的方式會因為使用其他類型的掃描器而改變。例如,如果使用的條碼掃描器使用藍芽,可能就需要某些序列通訊才能決定條碼掃描器的類型。如果條碼掃描器是隨插即用的卡片 (CompactFlash 或安全數位卡),則您可使用原生 Windows CE Storage Manager API 來決定條碼掃描器的類型。OpenNETCF 也提供 (.NET Compact Framework 的) Managed 類別,以存取其 Smart Device Framework 中的儲存卡 (在 OpenNETCF.IO.StorageCard 類別中),也可以原始程式碼的形式取得。

然而,此設計的目的在於將您新增額外條碼掃描器支援的工作減到最小。若要新增額外條碼掃描器的支援,您可建立兩個新類別:一個工廠類別和一個條碼掃描器類別。然後,您只需要更新外觀類別 BarcodeScannerFacade 即可支援額外的條碼掃描器。如需有關擴充樣式的詳細資訊,請參閱<支援額外的條碼掃描器>一節。

條碼掃描器範例

此範例是以 C# 使用 Visual Studio .NET 2003 針對 .NET Compact Framework 所建立,示範如何在不同的裝置上掃描條碼。本範例已經在 Symbol PDT 8100Intermec 740 這兩種裝置上測試過,您可以透過簡單的延伸將它應用在更多裝置。

此範例的使用者介面很簡單,如 [圖 2] 所示。

Aa446489.barcode_scanners_netcf_02(zh-tw,MSDN.10).gif

[圖 2] 條碼範例

使用者按「啟動」按鈕後,就可使用裝置上的觸發器來掃描條碼。完成條碼掃描之後,裝置就會在文字方塊中顯示使用者掃描的條碼。[圖 2] 中,使用者掃描了一本書的 ISBN 條碼。為了確認掃描的條碼,裝置會計算 ISBN 並將條碼影像拖曳到表單上。

程式碼逐步解說

在使用者介面中開始,「啟動」按鈕的程式碼如下所示。

private void startButton_Click(object sender, System.EventArgs e)
{
  barcodeScanner = BarcodeScannerFacade.GetBarcodeScanner();
  barcodeScanner.BarcodeScan += new
    BarcodeScanner.BarcodeScanEventHandler(barcodeScanner_BarcodeScan);
}

外觀類別 BarcodeScannerFacade 中的類別 (靜態) 方法 GetBarcodeScanner,用來擷取目前裝置上相關的條碼掃描器類別。條碼掃描器執行個體建立時,會設定事件處理常式來處理使用者所掃描的資料。該事件處理常式的程式碼如下所示。

private void barcodeScanner_BarcodeScan(object sender,
    BarcodeScannerEventArgs e)
{
    scanTextBox.Text = e.Data;
}

上述程式碼 (使用 Data 屬性) 將文字方塊 scanTextBox 的的文字設為事件引數 e 中提供的資料。這個簡單的程式碼就足以用來實作使用者介面。這項使用者介面實作的優點就是條碼掃描器外觀類別 — 及其所管理的類別 — 實作方式的結果。

您可使用下列程式碼範例實作外觀類別。

public class BarcodeScannerFacade
{
    public static BarcodeScanner GetBarcodeScanner()
    {
        BarcodeScannerFactory BarcodeScannerFactory = null;
        BarcodeScanner BarcodeScanner = null;

        string oemInfo = GetOemInfo();

        // Is this a Symbol device?
        if(oemInfo.IndexOf("Symbol") > -1)
            BarcodeScannerFactory =
                new SymbolScanner.SymbolBarcodeScannerFactory();

        // Is this an Intermec device?
        if(oemInfo.IndexOf("Intermec") > -1)
            BarcodeScannerFactory =
                new IntermecScanner.IntermecBarcodeScannerFactory();

        // Create a generic bar code reader object
        if(BarcodeScannerFactory != null)
            BarcodeScanner = BarcodeScannerFactory.GetBarcodeScanner();

        return BarcodeScanner;

    // GetOemInfo code ...
}

在您宣告泛用工廠和條碼掃描器執行個體之後,就會擷取原始設備製造商 (OEM) 的相關資訊。視該項資訊而定,會建立對應的條碼掃描器工廠執行個體,然後會使用該執行個體建立條碼掃描器物件。如此,就會傳回與裝置廠牌對應的泛用條碼掃描器執行個體。當然,在實際應用情況下會以 OEM 字串檢查更多詳細資料 (例如類型和機型),來決定條碼掃描器在該裝置上的實際實作。此外,如果條碼掃描器非相依於該裝置廠牌 (例如附接至擴充埠的條碼掃描器),您可以執行任何所需測試,決定使用的條碼掃描器。

從裝置取得 OEM 字串的程式碼如下所示。

private static string GetOemInfo()
{
    string oemInfo = new string(' ', 50);
    int result = SystemParametersInfo(SPI_GETOEMINFO, 50, oemInfo, 0);
    oemInfo = oemInfo.Substring(0, oemInfo.IndexOf('/0'));
    return oemInfo;
}

呼叫 Windows CE API 的 SystemParametersInfo,要求 OEM 資訊,此資訊由第一個參數 SPI_GETOEMINFO 指定。此呼叫使用下列 API 宣告。

[System.Runtime.InteropServices.DllImport("coredll.dll")]
private static extern int SystemParametersInfo(
    int uiAction, int uiParam, string pvParam, int fWinIni);
private const int SPI_GETOEMINFO = 258;

請注意,此程式碼應該能在大部分的 Pocket PC 上使用,但截至目前為止只在上述的 Symbol 和 Intermec 裝置上測試過。

接下來,本文將討論 BarcodeScannerBarcodeScannerFactory 這兩個抽象類別的實作,以及應用程式使用它們的方式。

用來建立條碼掃描器類別的基底類別使用下列程式碼實作。

public abstract class BarcodeScannerFactory 
{
    public abstract BarcodeScanner GetBarcodeScanner();
}

定義單一方法來建立條碼掃描器類別的執行個體,並使用下列程式碼實作該類別。

public abstract class BarcodeScanner : IDisposable
{    
    public BarcodeScanner()
    {
        if (Initialize())
            this.Start();
    }

    public abstract bool Initialize();
    public abstract void Start();
    public abstract void Stop();
    public abstract void Terminate();

    // Event
    public delegate void BarcodeScanEventHandler(object sender,
        BarcodeScannerEventArgs e);
    public event BarcodeScanEventHandler BarcodeScan;
    protected virtual void OnBarcodeScan(BarcodeScannerEventArgs e)
    {
        if (BarcodeScan != null)
            BarcodeScan(this, e);
    }

    // IDisposable code ...
}

如果掃描器可被初始化,掃描會在建構函式中啟動。需要由子類別 (InitializeStartStopTerminate) 實作的方法會和 BarcodeScan 事件一起宣告,此事件會在每次進行掃描時引發。請注意,IInitialize 方法的傳回值表示它是否成功。條碼掃描器類別會實作 IDisposable 介面,以便清除用過的資源。解構函式也會呼叫 Dispose 方法,因此您不需要明確呼叫 Dispose 方法。

事件引數使用下列程式碼定義。

public class BarcodeScannerEventArgs : EventArgs
{
    public BarcodeScannerEventArgs(string data)
    {
        this.data = data;
    } 
    private string data;
    public string Data
    {
        get { return data; }
    }
}

此時,事件引數可能只包含一項資訊 (字串),但可輕鬆擴充,提供每個掃描的詳細資訊。例如,Symbol 掃描器可能傳回使用者掃描的條碼類型 (也就是 EAN-13) 以及使用者掃描條碼的時間。如前所述,決定需要支援的事件引數是個好注意,因為之後進行變更表示您需要更新所有的條碼掃描器類別。

BarcodeScannerFactoryBarcodeScanner 基底類別用來為不同的裝置建立特定的類別。Symbol 裝置的條碼掃描器工廠類別如下所示。

public class SymbolBarcodeScannerFactory : BarcodeScannerFactory 
{
    public override BarcodeScanner GetBarcodeScanner() 
    {
        return new SymbolBarcodeScanner();
    }
}

此類別繼承基底工廠類別 BarcodeScannerFactory,並複寫 GetBarcodeScanner 方法以建立新的條碼掃描器類別。Intermec 裝置的對應工廠類別如下所示。

public class IntermecBarcodeScannerFactory : BarcodeScannerFactory 
{
    public override BarcodeScanner GetBarcodeScanner() 
    {
        return new IntermecBarcodeScanner();
    }
}

Intermec 裝置的工廠類別實作幾乎和 Symbol 工廠類別一模一樣,為另一台掃描器建立工廠類別只需要複製其中一個類別,然後取代前置詞 (Symbol 或 Intermec) 就可以了。

然而,更有趣的是個別條碼掃描器類別的實作。這裡有一點值得注意,Symbol 和 Intermec 都各自為其條碼掃描器提供 Managed 包裝程式 (直接從 .NET Compact Framework 程式碼取得)。這些包裝函式不包含在下載程式碼範例中,開發人員可另行向供應商取得。

接下來,讓我們看看 Symbol 條碼掃描器類別的開頭,如下列程式碼範例所示。

public class SymbolBarcodeScanner : BarcodeScanner 
{
    private Reader symbolReader = null;
    private ReaderData symbolReaderData = null;

    public override bool Initialize()
    {
        // If the scanner is already present, fail to initialize
        if(symbolReader != null)
            return false;

        // Create a new scanner; use the first available scanner
        symbolReader = new Reader();

        // Create the scanner data
        symbolReaderData = new ReaderData(ReaderDataTypes.Text,
            ReaderDataLengths.DefaultText);

        // Create the event handler delegate
        symbolReader.ReadNotify +=new

EventHandler(symbolReader_ReadNotify); // Enable the scanner with a wait cursor symbolReader.Actions.Enable(); // Set up the scanner symbolReader.Parameters.Feedback.Success.BeepTime = 0; symbolReader.Parameters.Feedback.Success.WaveFile = "//windows//alarm3.wav"; return true; }

此程式碼定義兩個執行個體 symbolReadersymbolReaderData,它們是掃描條碼的必要項目。初始設定會建立新的掃描器執行個體 (如果還沒有的話) 以及掃描器資料執行個體 (指定將掃描的資料傳回為文字)。事件處理常式會被設定、掃描器會被啟用,同時會設定一些掃描器參數。

若要啟動掃描器,請使用下列程式碼。

public override void Start() 
{
    // If you have both a scanner and data
    if((symbolReader != null) && (symbolReaderData != null))
        // Submit a scan
        symbolReader.Actions.Read(symbolReaderData);
}

在啟動掃描之前,必須先建立 symbolReader 類型的條碼掃描器物件執行個體和 symbolReaderData 類型的掃描器資料物件。

使用下列程式碼可實作事件處理常式。

private void symbolReader_ReadNotify(object sender, EventArgs e) 
{
    ReaderData readerData = symbolReader.GetNextReaderData();

    // If successful, scan
    if(readerData.Result == Results.SUCCESS) 
    {
        // Raise the scan event to the caller (with data)
        OnBarcodeScan(new BarcodeScannerEventArgs(readerData.Text));

        // Start the next scan
        Start();
    }
}

進行讀取時,掃描器資料執行個體 readerData 會和掃描的資料一起載入,如果掃描成功,就會隨掃描的資料 (字串) 引發泛用事件,隨後新的掃描就會啟動。

使用下列程式碼可停止掃描器。

public override void Stop() 
{
    // If you have a scanner
     if(symbolReader != null)
        // Cancel all pending scans
        symbolReader.Actions.Flush();
}

如果掃描器執行個體存在,所有擱置的掃描都會取消。

使用下列程式碼可終止 (移除) 條碼掃描器執行個體。

public override void Terminate()
{
    // If you have a scanner
    if(symbolReader != null)
    {
        // Disable the scanner
        symbolReader.Actions.Disable();

        // Free it up
        symbolReader.Dispose();

        // Indicate that you no longer have a scanner
        symbolReader = null;
    }

    // If you have a scanner data object
    if(symbolReaderData != null)
    {
        // Free it up
        symbolReaderData.Dispose();

        // Indicate that you no longer have a scanner
        symbolReaderData = null;
    }
}

掃描器和掃描器資料執行個體都會經過適當的處理和移除。此方法是從標準 Dispose 方法呼叫,表示它永遠不需要被明確呼叫。

使用下列程式碼可開始 Intermec 條碼掃描器的對應類別。

public class IntermecBarcodeScanner : BarcodeScanner 
{
    private BarcodeReader intermecReader = null;

    public override bool Initialize() 
    {
        // If a scanner is already present, fail to initialize
        if(intermecReader != null) 
            return false;

        // Create the event handler delegate
        intermecReader.BarcodeRead += new
                BarcodeReadEventHandler(intermecReader_BarcodeRead);

        // Set up the reader
        intermecReader.ThreadedRead(true);

        return true;
    }

宣告條碼掃描器執行個體 intermecReader 之後,Initialize 方法會建立執行個體、設定事件處理常式,並表示掃描器應在不同的背景執行緒上執行掃描作業。

Intermec 裝置不需要條碼掃描器的 StartStop 方法,因此它們沒有任何實作。使用下列程式碼可終止條碼掃描器。

public override void Terminate()
{
        // If you have a scanner
        if(intermecReader != null) 
        {
                // Free it up
                intermecReader.Dispose();

                // Indicate you no longer have a scanner
                intermecReader = null;
        }
}

如果掃描器執行個體存在,它就會被處理和移除。使用下列程式碼可實作事件處理常式。

private void intermecReader_BarcodeRead(object sender,
    BarcodeReadEventArgs bre)
{
        // Raise the read event to the caller (with data)
        OnBarcodeScan(new BarcodeScannerEventArgs(bre.strDataBuffer));
}

進行讀取時,會隨掃描的資料引發泛用事件,掃描的資料會和事件引數一起傳遞。若要支援額外的條碼掃描器,必須複製和修改後兩個類別其中之一,以支援特定的實作。

最後,在掃描條碼時所引發的事件 (即 BarcodeScan 事件) 會傳回使用者介面,此事件也包含下列程式碼。

string s = scanTextBox.Text.Substring(3, 9);
isbnLabel.Text = "ISBN " + s.Substring(0, 1) + "-" +
    s.Substring(1, 3) + "-" + s.Substring(4, 5) + "-" +
    isbnChecksum(s);

ISBN 會從掃描的 EAN-13 條碼 (適用於書籍 ISBN 條碼的標準) 計算,總和檢查碼會使用下列程式碼計算。

private string isbnChecksum(string isbn)
{
    int sum = 0;
    for(int i = 1; i < 10; i++)
        sum += Convert.ToInt32(isbn.Substring(i - 1, 1)) * (11 - i);
    int checksum = (11 - (sum % 11)) % 11;
    if(checksum < 10)
        return checksum.ToString();
    else
        return "X";
}

如下列程式碼所示,此事件也包含將條碼以表單型態繪製 (在 PictureBox 控制項中) 的程式碼。

Bitmap b = new Bitmap(pictureBox.Width, pictureBox.Height);
Graphics g = Graphics.FromImage(b);
g.Clear(SystemColors.Window);
Ean13 ean13 = new Ean13(scanTextBox.Text);
ean13.DrawEan13Barcode(g, new System.Drawing.Point(0, 0));
pictureBox.Image = b;
g.Dispose();

條碼的繪製採用 Code Project 網站上< 使用 C# 建立 EAN-13 條碼>(英文) 的範例,將其中的 Ean13 類別針對 .NET Compact Framework 稍微修改而成。

部署

視目標裝置而定,您可依下列方式部署 下載程式碼範例。由於授權的緣故,以下提及的檔案並未隨附於本文之下載程式碼範例中。開發人員可以分別向廠商取得這些檔案。

Symbol

此裝置必須使用下列檔案:

  • Symbol.Barcode.dll
  • Symbol.Barcode.xml
  • Symbol.dll
  • Symbol.xml

此外,Platform 資料夾中所有的預設檔案都必須複製到 Windows 資料夾中 (這通常會在冷開機時進行)。

注意:您必須停用紅外線連接埠的自動接收功能,掃描器才能運作。確保停用此選項的一個方式,就是將 IRDiscovery.reg 檔案放到 Application 資料夾中 (此檔案會在冷開機時載入)。
注意:下載程式碼範例只有在 Symbol PDT 8100 裝置上測試過。

Intermec

此裝置必須使用下列檔案:

  • Intermec.DataCollection.dll
  • itcscan.dll (在 Windows 資料夾中)
注意:條碼包裝函式只有在 Intermec 740 裝置上測試過。

支援額外的條碼掃描器

條碼掃描器樣式實作是專為讓您輕鬆加入額外條碼掃描器的支援而設計。以下是支援額外條碼掃描器所需的基本程序。在此範例中,新的掃描器稱為 Socket。

支援額外的條碼掃描器

  1. 建立名為 SocketBarcodeScannerFactory 的新類別。
  2. 建立名為 SocketBarcodeScanner 的新類別。
  3. 更新 BarcodeScannerFacade 類別,以測試和建立工廠和掃描器執行個體。

    工廠類別如下列程式碼範例所示。

    public class SocketBarcodeScannerFactory : BarcodeScannerFactory 
    {
        public override BarcodeScanner GetBarcodeScanner() 
        {
            return new SocketBarcodeScanner();
        }
    }
    

實際的條碼掃描器類別實作可能會有相當大的差距,但基本結構類似與下列的程式碼範例。

public class SocketBarcodeScanner : BarcodeScanner 
{
    private Scanner socketBarcodeScanner = null;

    public override bool Initialize() 
    {
        // If a scanner is already present, fail to initialize
        if(socketBarcodeScanner != null) 
            return false;

        // Create an event handler delegate
        socketBarcodeScanner.ScanEvent += new
                ScanEventHandler(socketBarcodeScanner_ScanEvent);

        socketBarcodeScanner.ScanInit();

        // Other necessary set up...

        return true;
    }

    public override void Start() 
    {
        // Code to start each scan...
    }

    public override void Stop() 
    {
        // Code to stop a scan...
    }

    public override void Terminate()
    {
        // If you have a scanner
        if(socketBarcodeScanner != null) 
        {
            socketBarcodeScanner.ScanDeinit();

            // Any other necessary code for cleaning up...

            // Free it up
            socketBarcodeScanner.Dispose();

            // Indicate that you no longer have a scanner
            socketBarcodeScanner = null;
        }
    }

    private void socketBarcodeScanner_ScanEvent(object sender,
        BarcodeReadEventArgs bre)
    {
        // Raise a read event to a caller (with data)
        OnBarcodeScan(new BarcodeScannerEventArgs(e.ScannedData));
    }

    public override void Dispose(bool disposing)
    {
        if (disposing)
        {
            // Code to clean up managed resources
            Terminate();
        }
        // Code to clean up unmanaged resources
    }
}

請注意,特定實作程式碼可能需要參考某些 Managed 程式庫才能存取條碼掃描器。如果沒有可用的 Managed 程式庫,您就必須實作 Managed 包裝函式,將原生 API 發佈為 Managed 類別。您可以參考 MSDN Library 中的& Microsoft .NET Compact Framework 上的 P/Invoke 和封送處理簡介>(英文) 文件和其他類似文件著手,這是撰寫此類 Managed 包裝函式的一個好方式。

在外觀類別 BarcodeScannerFacade 中,您可新增如下所示的程式碼。

if(testToSeeIfSocketBarcodeScanner)
    BarcodeScannerFactory =
        new SocketScanner.SocketBarcodeScannerFactory();

在此程式之前,視此類型 (通訊端) 條碼掃描器是否找到而定,您還必須加入設定測試變數 testToSeeIfSocketBarcodeScanner 的程式碼。

結論

將應用程式使用條碼掃描器的方式,以及條碼掃描器實際在特定裝置上實作的方式加以區分,可簡化您行動方案的維護。日後需要更新裝置時,這個開頭的額外小動作可能會讓您值回票價。您可以在其他特定裝置實作上使用相同的設計,例如數位像機和定位裝置。

 

http://msdn.microsoft.com/zh-tw/library/aa446489.aspx

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值