Export (0) Print
Expand All

Bar Code Scanners with the .NET Compact Framework

.NET Compact Framework 1.0
 

Christian Forsberg
businessanyplace.net

March 2006

Applies to:
   Windows Mobile 2003–based Pocket PCs
   Microsoft Visual Studio .NET 2003
   Microsoft .NET Compact Framework version 1.0

Summary: Learn how to make your applications use bar code scanners in a generic way—ndependent of the specific bar code scanners that are used on different devices. Using the design patterns Façade and Factory, the implementation not only supports multiple bar code scanners, but it also makes it easy to add support for other bar code scanners. After a brief discussion about bar code scanners and the bar code scanner pattern, a download code sample, written in C#, demonstrates the use of the pattern and technologies. (20 printed pages)


Download Barcode Scanners NETCF.msi from the Microsoft Download Center.

Contents

Introduction
Bar Codes
Bar Code Scanners
Barcode Scanner Pattern
Bar Code Scanner Example
Code Walkthrough
Deployment
Supporting Additional Bar Code Scanners
Conclusion

Introduction

Professionals use bar code scanners in various business scenarios—mostly in logistic applications for transportation, warehouses, libraries, and laboratories. There is great power in tracking products by article numbers or even unique serial numbers from manufacturing all the way to the customer—and even if the product comes back for support. Because the technology makes it very cost efficient to capture information at many points, professionals can easily collect detailed information and save it for later analysis and decision support.

Because many of the traditional bar code applications are mobile, the match with mobile devices like a Pocket PC is obvious. Therefore, various suppliers offer a lot of different bar code solutions. Many integrated devices have a bar code scanner built in, but recent solutions make use of wireless technology (like Bluetooth) to separate the bar code scanner from the mobile device. The need to make use of these bar code scanners directly from the mobile devices is obvious, and, therefore, many suppliers offer software development kits (SDKs) for their respective devices. Many of the large suppliers even offer ready-made development kits for the latest tools (read managed APIs for .NET Compact Framework); therefore, many enterprise solutions already make use of these libraries to integrate the bar code scanners with the business solution.

In any enterprise solution that is intended to be used for a long period of time, it is desirable to separate the implementation of the business logic from the technical infrastructure. A typical example is the use of bar code scanners because they are frequently used in many logistic solutions. However, because there are no common standards for how an application can access a bar code scanner, most implementations are made for a specific bar code scanner or even a specific device. That implementation probably works for the first project, and for some time, but when the devices need to be replaced, problems arise. Using an abstraction layer that can separate the use of the bar code scanner from the actual implementation on a different device can resolve the problem. When the old devices need to be replaced, developers can update the application to support the new device and bar code scanner. Another benefit with such an abstraction layer is that the application can support both the old and new devices simultaneously, which allows for a smooth transition between the devices.

This article discusses a pattern for such an abstraction layer, as mentioned earlier. The article's download code sample demonstrates the theory.

Bar Codes

Bar codes, in their primary forms, have been around for more than 50 years, and they were commercialized almost 40 years ago. The bars and spaces in each symbol are grouped in such a way to represent a specific ASCII character. Interpreting these groups is based on a particular set of rules called symbologies. Currently, more than 400 symbologies are in use.

Some of the bar code symbologies are established as standards for identifying certain items. Table 1 contains some examples.

Table 1. The established standards and the corresponding bar code symbologies

Established standard Items to identify Bar code symbology
UPC–A or UPC–E Items for sale in the United States and Canada UPC/EAN
EAN–8 or EAN–13 Items for sale worldwide UPC/EAN
ISBN, ISSN, and Booklan Books and periodicals EAN–13 with UPC/EAN
UCC–128, EAN–128, or SSCC–18 Shipping cartons Code 128
SCC–14, EAN–14 Shipping cartons Interleaved 2 of 5 or Code 128
SSCC–18 Shipping cartons Code 128
SISAC or SICI Code Serial numbers for serial publications Code 128
MICR Bank checks MICR E-13B or CMC–7

One bar code symbology that almost all of us have come in contact with is the EAN-13 bar code, which is used for books and periodicals. EAN is the acronym for European Article Numbering system (also called JAN in Japan) and is a European version of the universal product code (UPC). The EAN–13 bar code has the same size requirements and a similar encoding scheme as UPCs. The EAN–13 bar code is composed of 13 digits, which are made of the following sections: the first two or three digits are the country code, the next five to seven digits are the manufacturer code, the next three to five digits are the product code, and the last digit is the checksum digit. An International Standard Book Number (ISBN) or Booklan bar code is an EAN–13 symbol—the first nine digits of the ISBN number are preceded by the digits 978 and the additional checksum digit.

Bar Code Scanners

There are basically three different types of bar code scanners for Pocket PC:

  • Built-in
  • Wireless
  • Expansion card

The built-in scanners are probably the most secure solution because most of these devices are also rugged like the PPT 8800 Series from Symbol and the 700 Series from Intermec. Being very solid, the built-in type is also the least flexible option because the bar code scanners cannot be shared among devices.

An excellent example of a wireless bar code scanner is the BaracodaPencil from Baracoda. The BaracodaPencil uses Bluetooth to communicate with the Pocket PC, and it can even be used as a Pocket PC stylus. Of course, there are full-sized wireless bar code scanners like the Voyager BT from Metrologic. (You can also explore the product by using the three-dimensional demonstration). These types of devices have an advantage: they can be shared between different Pocket PCs. However, because other data entry is often needed along with the bar code scanning, it might be a problem to manage two devices at the same time.

When it comes to expansion card bar code scanners, there are different types of card standards. Because many Pocket PCs support them, CompactFlash (CF) cards are very popular. However, there are PC cards and Secure Digital (SD) cards as well. For example, the Secure Digital Scan Card 3E is a very interesting option. It is very small (1.14 in. x 1.14 in. x 0.55 in.) and light (0.26 oz.), and it works with most of the newer Pocket PCs. Being very flexible, the risk with using expansion card bar code scanners is that they are not suitable for very rough handling and for use in rough environments.

An alternative to using a physical bar code scanner is using a digital camera to take pictures of a bar code and then using software to interpret the bar code. There are not many commercial (or free) solutions for Pocket PC yet, but as digital cameras improve their resolutions, digital cameras will probably be an interesting option in the future. With many Smartphones also equipped with digital cameras, a generic .NET Compact Framework solution can support Smartphones as well.

Barcode Scanner Pattern

The purpose of the barcode scanner pattern is to separate an application's use of a bar code scanner from the actual implementation of the bar code scanner on a specific device.

The pattern is a combination of two common design patterns: the facade pattern and the factory pattern.

A class diagram of the pattern looks like Figure 1.

Figure 1. Bar code scanner pattern

There are two generic abstract bar code scanner classes: the factory base class, BarcodeScannerFactory, and the bar code scanner base class, BarcodeScanner. The specific bar code scanner classes (for example, Symbol or Intermec) inherit these classes. The main façade class BarcodeScannerFacade determines on which device the code is running. The façade class is also responsible for returning a bar code scanner object of the correct type. Client code (usually in a form) would call the static method GetBarcodeScanner on the façade class BarcodeScannerFacade class to get a factory instance—depending on what device the code was running. The façade class then calls the method GetBarcodeScanner on that factory to get an instance of the correct bar code scanner.

One key aspect of the pattern is how to implement the event BarcodeScan that is raised when a new scan is made. The event itself is probably very simple (much like the example that follows), but the event arguments demand some thought. Early on, it is important for you to decide what type of information the application needs about each scan. Is it sufficient to store only the scanned data as a text string? Or will the application support more than one bar code format and thereby require the event to deliver information about what standard the bar code conforms to (for example, EAN–13 for ISBN bar codes). Although not all scanners support all of the required information, those scanners provide static information instead. For example, if a scanner cannot deliver information about the bar code standard, a standard needs to be hard-coded in the returned event arguments.

Currently, the pattern implementation supports only bar code scanners on two devices from Symbol and Intermec. The pattern also supports only bar code scanners that are built into the respective device. The way that the façade class determines which bar code scanner to use changes when other types of scanners are used. For example, if a bar code scanner that uses Bluetooth is used, some serial communication is probably required to determine the type of bar code scanner. If the bar code scanner is a plug-in card (CompactFlash or Secure Digital cards), you can use the native Windows CE Storage Manager APIs to determine the type of bar code scanner. OpenNETCF also provides managed classes (for the .NET Compact Framework) to access storage cards (in the OpenNETCF.IO.StorageCard class) in its Smart Device Framework, which is also available as source code.

However, the purpose of the design is to minimize work when you add support for additional bar code scanners. To add a support for an additional bar code scanner, you create two new classes: one factory class and one bar code scanner class. Then, only the façade class BarcodeScannerFacade needs to be updated to support the additional bar code scanner. For more information about extending the pattern, see the section Supporting Additional Bar Code Scanners.

Bar Code Scanner Example

This example was created by using Visual Studio .NET 2003 in C# and by targeting the .NET Compact Framework. The example shows how to scan bar codes on different devices. The example has been tested on two devices, the Symbol PDT 8100 and the Intermec 740, but the example is designed to be easily extended to work on more devices.

The user interface of the example is simple, as shown in Figure 2.

Figure 2. Bar code example

When the user taps the Start button, the user can scan a bar code by using the trigger on the device. When the user completes scanning the bar code, the device displays the bar code that the user scanned in the text box. In Figure 2, the user scanned the ISBN bar code of a book. To confirm the scanned bar code, the device calculates the ISBN and draws the bar code image on the form.

Code Walkthrough

Starting in the user interface, the code for the Start button looks like the following.

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

The class (static) method GetBarcodeScanner in the façade class BarcodeScannerFacade is used to retrieve a bar code scanner class that is relevant on the current device. When the bar code scanner instance is created, an event handler is set up to handle data that the user has scanned. The code for that event handler looks like the following.

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

The preceding code simply set the text of the text box scanTextBox to the data (using the Data property) that is provided in the event arguments e. This simple code is all that is needed to implement the user interface. The beauty of this user interface implementation is a result of how the bar code scanner façade class—and the classes managed by it—is implemented.

You can implement the façade class by using the following code example.

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 ...
}

After you declare the generic factory and bar code scanner instances, information about the original equipment manufacturer (OEM) is retrieved. Depending on that information, the corresponding bar code scanner factory instance is created, and using that instance, the bar code scanner object is created. In this way, a generic bar code scanner instance corresponding to the device brand is returned. Of course, in a real-world scenario, the OEM string can be checked for more details (such as type and model) to determine the exact implementation for the bar code scanner on that device. Also, if the bar code scanner is not dependent on the device brand (such as a bar code scanner attached to an expansion port), you can run any required test to determine the bar code scanner that is used.

The code to get the OEM string from the device looks like the following.

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;
}

A call is made to the Windows CE API SystemParametersInfo, requesting the OEM information, which the first parameter, SPI_GETOEMINFO, specifies. The call uses the following API declarations.

[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;

Note that this code should work on most Pocket PCs, but it was tested only on the Symbol and Intermec devices mentioned earlier.

Next, this article looks at the implementation of the two abstract classes, BarcodeScanner and BarcodeScannerFactory, and how the application uses them.

The base class used to create bar code scanner classes is implemented by using the following code.

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

A single method is defined to create an instance of a bar code scanner class, and that class is implemented by using the following code.

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 ...
}

If the scanner can be initialized, a scan is started in the constructor. The methods that need to be implemented by subclasses (Initialize, Start, Stop, and Terminate) are declared along with the event BarcodeScan, which is raised whenever a scan is made. Note that the Initialize method's return value indicates whether it was successful or not. The bar code scanner class implements the IDisposable interface to enable a graceful cleanup of the resources that were used. The destructor also calls the Dispose method, and, therefore, there is no need to call the Dispose method explicitly.

The event arguments are defined by using the following code.

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

At the moment, the event arguments can hold only a single piece of information (a string), but they can easily be extended to provide more of the information that is available for each scan. For example, the Symbol scanner can return what type of bar code the user scanned (that is, EAN–13) and when the user scanned the bar code. Early on, it is a good idea to decide which event arguments need to be supported because making a change later means that you need to update all of the bar code scanner classes.

The BarcodeScannerFactory and BarcodeScanner base classes are used for creating specific classes for different devices. The bar code scanner factory class for the Symbol device looks like the following.

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

The class inherits the base factory class BarcodeScannerFactory and overrides the method GetBarcodeScanner to create a new bar code scanner class. The corresponding factory class for the Intermec device looks like the following.

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

The factory class for the Intermec device has an almost identical implementation as the Symbol factory class, and to create a factory class for another scanner would be a matter of simply copying one of these classes and replacing the prefix (Symbol or Intermec).

More interesting, though, is the implementation of the respective bar code scanner classes. It is important to note that both Symbol and Intermec provide managed wrappers (directly available from .NET Compact Framework code) for their respective bar code scanners. These wrappers are not included in the download code sample, but they are available to developers from the respective vendor.

Next, look at the beginning of the Symbol bar code scanner class, as shown in the following code example.

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;
    }

The code defines the two instances symbolReader and symbolReaderData that are required to scan bar codes. The initialization creates a new scanner instance (if one doesn't already exist) and a scanner data instance (specifying to return scanned data as text). The event handler is set up, the scanner is enabled, and some scanner parameters are set.

To start the scanner, use the following code.

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

Instances of a bar code scanner object of type symbolReader and a scanner data object of type symbolReaderData need to be created before a scan can be started.

The event handler is implemented by using the following code.

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();
    }
}

When a read is made, the scanner data instance readerData is loaded with the scanned data, and if the scan is successful, the generic event is raised with the scanned data (string). Then, a new scan is started.

The scanner is stopped by using the following code.

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

If a scanner instance exists, all pending scans are cancelled.

The bar code scanner instances are terminated (removed) by using the following code.

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;
    }
}

Both the scanner and scanner data instances are gracefully disposed of and removed. This method is called from the standard Dispose method, which means that it never needs to be explicitly called.

The corresponding class for the Intermec bar code scanner begins by using the following code.

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;
    }

After the bar code scanner instance intermecReader is declared, the Initialize method creates the instance, sets up the event handler, and indicates that the scanner should perform scan operations on a separate background thread.

The methods to Start and Stop the bar code scanner are not needed for an Intermec device, and therefore they don't have any implementation. The bar code scanner is terminated by using the following code.

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;
        }
}

If a scanner instance exists, it is disposed of and removed. The event handler is implemented by using the following code.

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

When a read is made, the generic event is raised with the scanned data, which is passed with the event arguments. To support an additional bar code scanner, one of the latter two classes needs to be copied and modified to support the specific implementation.

Finally, returning to the user interface, the event that was raised when a bar code was scanned, the BarcodeScan event, also included the following code.

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

The ISBN is calculated from the scanned EAN–13 bar code (the standard that is used for ISBN bar codes on books), and the checksum is calculated by using the following code.

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";
}

The event also included the code to draw the bar code on the form (in a PictureBox control) by using the following code.

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();

The drawing of the bar code was made by using a somewhat modified (and ported to the .NET Compact Framework) version of the class (Ean13) in the sample Creating EAN-13 Barcodes with C# on the Code Project Web site.

Deployment

You can deploy the download code sample as follows, depending on the target device. The following files that are mentioned are not distributed with this article's download code sample because of reasons related to licensing. However, the files are available to developers from the respective vendor.

Symbol

The following files are required on the device:

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

It is also necessary that all of the default files in the Platform folder are copied to the Windows folder (this happens normally during a cold boot).

Note   You need to disable the automatic receive function of the infrared port to make the scanner work. One way of making sure this option is disabled is to put the IRDiscovery.reg file in the Application folder (this file is loaded on a cold boot).
Note   The download code sample has been tested only on a Symbol PDT 8100 device.

Intermec

The following files are required on the device:

  • Intermec.DataCollection.dll
  • itcscan.dll (in Windows folder)
Note   The Barcode Wrapper has been tested only on the Intermec 740 device.

Supporting Additional Bar Code Scanners

The bar code scanner pattern implementation was designed to make it easy to add support for other bar code scanners. The following is a basic procedure that is necessary to support an additional bar code scanner. In this example, the new scanner is named Socket.

To support an additional bar code scanner

  1. Create a new class named SocketBarcodeScannerFactory.
  2. Create a new class named SocketBarcodeScanner.
  3. Update the BarcodeScannerFacade class to test for and create the factory and scanner instance.

    The factory class is like the following code example.

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

Implementing the actual bar code scanner class might vary a lot, but the basic structure is like the following code example.

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
    }
}

Note that the specific implementation code probably needs to reference some managed libraries to access the bar code scanner. If no managed libraries are available, you need to implement a managed wrapper that publishes the native API as managed classes. A good starting point for writing such a managed wrapper is the article An Introduction to P/Invoke and Marshaling on the Microsoft .NET Compact Framework and other similar articles in the MSDN Library.

In the façade class BarcodeScannerFacade, you can add code that looks like the following.

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

Before this code, you also need to add code that sets the test variable testToSeeIfSocketBarcodeScanner depending on whether a bar code scanner of this type (socket) was found or not.

Conclusion

Separating how your application uses bar code scanners and how the bar code scanners are actually implemented on a specific device will ease maintenance of your mobile solution. When it's time to upgrade the devices, this initial and relatively small extra effort will probably pay off significantly. You can use the same design with other device-specific implementations, such as digital cameras and positioning equipment.

Show:
© 2014 Microsoft