Introduction
This is a follow up to the WPF Barcode Software project. It shows how we can use the Microsoft Silverlight technology to build a barcode software application. The nice thing about this barcode software is that you can run it in any browser that supports Silverlight. The source files requires at least Visual Web Developer 2008 Express Edition in order to compile.
The Project
The project consists of two C# subprojects:
(1) SilverlightBarcodeClassLibrary
This library is derived from the source code of the Code39 barcode of the WPF Barcode Software project. The input and output properties and the methods of the Barcodes
class are almost identical. For your convenience, they are reproduced below:
Input Properties
BarcodeType
- There are many types of barcodes used in real life. For example, those used in retail are different from those used in warehouses and logistics. Currently, the barcode library implements a simple but widely used barcode symbology known as Code 39. This barcode is also known as Code 3 of 9. This barcode accepts only upper case characters 'A' to 'Z', the numeric digits '0' to '9', and a few special characters. If you enter any other characters to the Data
string, they will be ignored and filtered away.
The Code 39 barcode has the advantage of being simple, as each of the characters are represented by a pattern of 10 alternating white and black bars. However, because the algorithm does not include much compression, the resulting barcode out is not very dense. In other words, you get a rather long barcode for a short data string.
Data
- This is the data to be encoded. For our WPF application, we have used "1234567" as the Data
input string.
CheckDigit
- Some barcodes specify that a check digit must be included into the barcode. The check digit is usually an additional character (or several characters) that is appended to the input Data
string and encoded into the barcode. The CheckDigit
helps the scanner to verify that the data that it reads is correct and complete. For the Code39 barcode, the CheckDigit
is optional. You can specify Yes
or No
to include or exclude it.
Main Method
encode()
- After you have specified the input properties, you can start letting the barcode class to create the black and white bars. This is done by calling the method encode()
. When this is done, you can start retrieving the results using the output properties of the Barcodes
class.
Output Properties
EncodedData
- This is the result returned by the Barcodes
after you have called the encode()
method. The EncodedData
returns a string in the form "twtwttwtttwtwttttwttwwttwtwttwttwtwttt". The "t" represents a thin bar, while the "w" represents a thick bar. A thick bar is usually thrice the width of a thin bar.
The way to interpret the result is that each character indicates alternating bar colors. For example, for "twtw", the first "t" will be a thin black bar, the second "w" will be a thick white bar, the third "t" will be a thin black bar, and the fourth "w" will be a thick white bar.
Our WPF application will use the string returned by EncodedData
to draw a series of alternating black and white rectangles.
HumanText
- This is a text that is usually placed below the barcode. The HumanText
helps a person to read the content of the barcode when a scanner is not available. The HumanText
is usually identical to the input Data
, but that is not always the case. Sometimes, the HumanText
will be formatted with special Start/Stop "*" characters; otherwise, it will include the extra CheckDigit
. Our WPF application will use the string returned by HumanText
to draw the human readable text below the barcode.
(2) SilverlightBarcodeApplication - A Silverlight UserControl
The layout of the control consists of mainly a Canvas
to hold the barcode and a TextBlock
for the human readable text. The default value of the TextBlock
is "1234", and it marks the location where the human readable text of the barcode will be located. The barcode is located exactly on top of the human readable text. All the rest of the grid cells that surrounds the Canvas
and TextBlock
are considered quiet zones of the barcode -- they are deliberately left blank so that the scanner will not confuse anything in them with the actual barcode.
The following is the source code for Page.xaml. Set ShowGridLines
to True
to see the layout:
<UserControl x:Class="SilverlightBarcodeApplication.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="270" Height="100" Loaded="UserControl_Loaded">
<Grid x:Name="grdLayoutRoot" Background="White" Width="270"
Height="100" ShowGridLines="False">
<Grid.RowDefinitions>
<RowDefinition Height="10"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="10"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"></ColumnDefinition>
<ColumnDefinition Width="250"></ColumnDefinition>
<ColumnDefinition Width="10"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Canvas x:Name="MyCanvas" Width="250" Height="50"
Grid.Row="1" Grid.Column="1" />
<TextBlock x:Name="MyText" Width="250" Height="30" Text="1234"
Grid.Row="2" Grid.Column="1" TextAlignment="Center" FontSize="16"/>
</Grid>
</UserControl>
The barcode is drawn in the UserControl_Loaded
method when the control is loaded.
The steps are rather straightforward. The control first uses the Barcode library to return a string representing the bars of the barcode (known as the encodedData
). From the encodedData
, it is able to find the sum total of the number of thin bars that is able to fit into the Canvas
width. (By the way, a thick bar is thrice the width of a thin bar). This sum total is known as the encodedLength
.
It then finds the width of the smallest bar in WPF coordinates (known as barWidth
) by dividing the width of the Canvas
by the encodedLength
(the sum total of the number of thin bars).
float barWidth = (float)(this.MyCanvas.Width / encodedLength);
The barWidth
is then used to draw the individual rectangles of the barcode. In this way, we are able to produce a barcode that fits into the Canvas
exactly.
The following is the source code for the Usercontrol_Loaded
method:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
Me.BarcodeSoftware.Barcode.Barcodes barcode =
new Me.BarcodeSoftware.Barcode.Barcodes();
barcode.BarcodeType =
Me.BarcodeSoftware.Barcode.Barcodes.BarcodeEnum.Code39;
barcode.Data = "123456";
barcode.encode();
string encodedData = barcode.EncodedData;
MyText.Text = barcode.HumanText;
int encodedLength = 0;
for (int x = 0; x < encodedData.Length; x++)
{
if (encodedData[x] == 't')
encodedLength++;
else if (encodedData[x] == 'w')
encodedLength = encodedLength + 3;
}
float barWidth = (float)(this.MyCanvas.Width / encodedLength);
if (barWidth < 1)
barWidth = 1;
float thickWidth = barWidth * 3;
double incrementWidth = 0;
int swing = 0;
for (int x = 0; x < encodedData.Length; x++)
{
Brush brush;
if (swing == 0)
brush = new SolidColorBrush(Colors.Black);
else
brush = new SolidColorBrush(Colors.White);
if (encodedData[x] == 't')
{
Rectangle r = new Rectangle();
r.Fill = brush;
r.Width = barWidth;
r.Height = this.MyCanvas.Height;
r.SetValue(Canvas.LeftProperty, incrementWidth);
r.SetValue(Canvas.TopProperty, 0.0);
MyCanvas.Children.Add(r);
incrementWidth = incrementWidth + ((barWidth));
}
else if (encodedData[x] == 'w')
{
Rectangle r = new Rectangle();
r.Fill = brush;
r.Width = 3 * barWidth;
r.Height = this.MyCanvas.Height;
r.SetValue(Canvas.LeftProperty, incrementWidth);
r.SetValue(Canvas.TopProperty, 0.0);
MyCanvas.Children.Add(r);
incrementWidth = incrementWidth + (3 * (barWidth));
}
if (swing == 0)
swing = 1;
else
swing = 0;
}
}
}
Further Improvements
A further improvement on the source code is to override the OnRender
function of the control. For further updates on this project, please visit my Barcode Software project.
History
- 01 May 2009: v0.1 - WPF Barcode library with limited number of barcodes. Starting with the Code 39 barcode.
- 18 May 2009 : v0.2 - My Silverlight barcode software is built using the same code base of the WPF Barcode library.