Advanced Barcode Generation System for Code 39 Standards






4.56/5 (11 votes)
Easily develop software to create fully custom Code 39 Barcodes for printing on Avery 8167 labels (document and box labels, or more based on customization).
- Download ITS Barcode Generation System v2.0 - 118 KB
- Download ITS Barcode System v2.0 (source code) - 383 KB
Download ITS Barcode Generation System v1.0 (application) - 121 KBDownload ITS Barcode System v1.0 (source code) - 404 KB
Introduction
The ITS, LLC Barcode Generation System generates C39 Barcode Labels to be printed on Avery 8167 labels. The software was developed for printing labels to be used on document boxes and documents (both actual documents and chain of custody logs) to track documents with boxes, etc.
This software allows for the following on label creation and configuration:
- Box Label Printing (80 unique labels per page)
- Document Jaclet Label Printing (40 unique labels per page, double entry for CCT)
- Automatic scanning of box barcode label to produce document labels
- Advanced configuration of drawing styles on barcodes
- Configuration of printing options for physical delivery of barcode page generation
Background
In terms of background on the software; the software was designed to print on the Avery 8167 labels, which has 80 labels per page -- however, with some configuration, you can use it to print on other style labels as well.
The software is developed on the Microsoft .NET Framework, and heavily uses the Microsoft .NET GDI+ system for drawing barcodes. It does not use a font to write the barcodes.
Using the Code
The code is fairly straightforward, and is very well commented. But as always, if you have any questions or comments, don't hesitate to contact me or leave a comment/question on the CodeProject page.
There are a few direct exerts; well actually, it's almost the complete code from the main Barcode Workspace below.
This is the main Barcode Generation System, allowing for the generation of each barcode image:
Public Class mainBarcodeWorkspace
Private _encoding As Hashtable = New Hashtable
Private Const _wideBarWidth As Short = 2
Private Const _narrowBarWidth As Short = 1
Private Const _barHeight As Short = 31
'Here we define the page counters -- this comes into play later!
Public totalPages As Integer = 1
Public curPage As Integer = 0
'Create a new box scan form
Public boxScanFrm As boxScan = New boxScan
'Declare the return timer countdown (seconds before return to the box scanner)
Public returnTimer As Integer = 15
'Define the main barcode canvas used for the master page
Dim barcodeCanvas As Bitmap
'Declare the printing object
'(used later for sending the barcode canvas to a printer)
Private WithEvents m_PrintDocument As Printing.PrintDocument
#Region "Barcode Generation System"
'This adds keys to the encoding hashtable,
'which tells us exactly what we need to draw later in GDI
'But more or less, these are the encoding bits
'for each of the Code39 allowable characters
Sub ITS_BarcodeC39()
_encoding.Add("*", "bWbwBwBwb")
_encoding.Add("-", "bWbwbwBwB")
_encoding.Add("$", "bWbWbWbwb")
_encoding.Add("%", "bwbWbWbWb")
_encoding.Add(" ", "bWBwbwBwb")
_encoding.Add(".", "BWbwbwBwb")
_encoding.Add("/", "bWbWbwbWb")
_encoding.Add("+", "bWbwbWbWb")
_encoding.Add("0", "bwbWBwBwb")
_encoding.Add("1", "BwbWbwbwB")
_encoding.Add("2", "bwBWbwbwB")
_encoding.Add("3", "BwBWbwbwb")
_encoding.Add("4", "bwbWBwbwB")
_encoding.Add("5", "BwbWBwbwb")
_encoding.Add("6", "bwBWBwbwb")
_encoding.Add("7", "bwbWbwBwB")
_encoding.Add("8", "BwbWbwBwb")
_encoding.Add("9", "bwBWbwBwb")
_encoding.Add("A", "BwbwbWbwB")
_encoding.Add("B", "bwBwbWbwB")
_encoding.Add("C", "BwBwbWbwb")
_encoding.Add("D", "bwbwBWbwB")
_encoding.Add("E", "BwbwBWbwb")
_encoding.Add("F", "bwBwBWbwb")
_encoding.Add("G", "bwbwbWBwB")
_encoding.Add("H", "BwbwbWBwb")
_encoding.Add("I", "bwBwbWBwb")
_encoding.Add("J", "bwbwBWBwb")
_encoding.Add("K", "BwbwbwbWB")
_encoding.Add("L", "bwBwbwbWB")
_encoding.Add("M", "BwBwbwbWb")
_encoding.Add("N", "bwbwBwbWB")
_encoding.Add("O", "BwbwBwbWb")
_encoding.Add("P", "bwBwBwbWb")
_encoding.Add("Q", "bwbwbwBWB")
_encoding.Add("R", "BwbwbwBWb")
_encoding.Add("S", "bwBwbwBWb")
_encoding.Add("T", "bwbwBwBWb")
_encoding.Add("U", "BWbwbwbwB")
_encoding.Add("V", "bWBwbwbwB")
_encoding.Add("W", "BWBwbwbwb")
_encoding.Add("X", "bWbwBwbwB")
_encoding.Add("Y", "BWbwBwbwb")
_encoding.Add("Z", "bWBwBwbwb")
End Sub
'This returns a color associated with the current line drawing
'in GDI, since it's a barcode we primarly want a contrasting
'color and a light background color, so depending on what
'the character is (whether it's a char or white space) we add color
Protected Function getBCSymbolColor(ByVal symbol As String) _
As System.Drawing.Brush
getBCSymbolColor = Brushes.Black
If symbol = "W" Or symbol = "w" Then
getBCSymbolColor = Brushes.White
End If
End Function
'Now we determine whether or not we are going to be drawing
'a small or large BC bar on this character code
Protected Function getBCSymbolWidth(ByVal symbol As String) As Short
getBCSymbolWidth = _narrowBarWidth
If symbol = "B" Or symbol = "W" Then
getBCSymbolWidth = _wideBarWidth
End If
End Function
'Now the fun part, this function is called to generate the actual barcode
Protected Overridable Function GenerateBarcodeImage(ByVal imageWidth As Short, _
ByVal imageHeight As Short, ByVal Code As String) As IO.MemoryStream
'Declare a new bitmap canvas to store our new barcode
'(well, it will be new -- we will make it soon)!
Dim b As New Bitmap(imageWidth, imageHeight, _
Imaging.PixelFormat.Format32bppArgb)
'Create the actualy canvas associated with the barcode drawing
Dim canvas As New Rectangle(0, 0, imageWidth, imageHeight)
'Create our graphics object from our barcode canvas
Dim g As Graphics = Graphics.FromImage(b)
'Fill the drawing with a white background
g.FillRectangle(Brushes.White, 0, 0, imageWidth, imageHeight)
'Draw the "eye candy" items on the barcode canvas
'Here we are drawing the gradient directly behind the barcode are at the top
g.FillRectangle(New Drawing2D.LinearGradientBrush(_
New Drawing.RectangleF(1, 1, 169, 30), Color.White, _
Color.LightGray, Drawing2D.LinearGradientMode.Vertical), 1, 1, 169, 30)
'Now we draw the seperation line (under barcode)
'and the liner gradient background
g.FillRectangle(New Drawing2D.LinearGradientBrush(_
New Drawing.RectangleF(1, 34, 169, 15), Color.LightGray, _
Color.White, Drawing2D.LinearGradientMode.Vertical), 1, 34, 169, 15)
g.FillRectangle(New SolidBrush(Color.Black), 1, 33, 169, 1)
'Now that we have the "fine art" drawn,
'let's switch over to high-quality rendering for our text and images
'However, we are using SingleBitPerPixel because when
'printed it appears sharper as opposed to anti-aliased
g.TextRenderingHint = Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit
g.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
g.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
g.CompositingQuality = Drawing2D.CompositingQuality.HighQuality
'If we are printing a box label then we need to add a side image
'and a "BOX" announcment on the right.
If boxNumber.Enabled = False Then
g.DrawImage(My.Resources.Shipping, 10, 2, 23, 23)
g.DrawString("BOX", New Font("Tahoma", 10, _
FontStyle.Bold), New SolidBrush(Color.Silver), 129, 7)
'Write out the original barcode ID, and preceed it with "BOX"
g.DrawString("Box " & Code, New Font("Tahoma", _
8, FontStyle.Bold), New SolidBrush(Color.Black), 3, 34)
Else
'Write out the original barcode ID
g.DrawString(Code, New Font("Tahoma", 8, FontStyle.Bold), _
New SolidBrush(Color.Black), 3, 34)
End If
'Write out a lighter barcode generation script version
'on the right (again, eye candy)
g.DrawString("ITS v2.0", New Font("Tahoma", 8, _
FontStyle.Bold), New SolidBrush(Color.Gray), 113, 34)
'Now that we are done with the high quality rendering, we are going
'to draw the barcode lines -- which needs to be very straight, and not blended
'Else it may blur and cause complications with the barcode
'reading device -- so we won't take any chances.
g.TextRenderingHint = Drawing.Text.TextRenderingHint.SystemDefault
g.SmoothingMode = Drawing2D.SmoothingMode.None
g.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor
g.CompositingQuality = Drawing2D.CompositingQuality.Default
'Code has to be surrounded by asterisks to make it a valid C39 barcode,
'so add "*" to the front and read of the barcode
Dim UseCode As String = String.Format("{0}{1}{0}", "*", Code)
'Define a starting X and Y position for the barcode
Dim XPosition As Short = 1
Dim YPosition As Short = 1
'Initialize our IC marker, and give a default of false
'This is used to track what? Incorrectly assigned
'characters for the barcode (ones that won't match
'C39 standards) So we don't use them, and mark it as invalid.
Dim invalidCharacter As Boolean = False
'Declare our current character string holding variable
Dim CurrentSymbol As String = String.Empty
'THIS PART IS *ONLY* FOR CALCULATING THE WIDTH OF THE BARCODE TO CENTER IT!
'Begin at the starting area of our FINAL rendered barcode value
For j As Short = 0 To CShort(UseCode.Length - 1)
'Set our current character to the character space of the barcode
CurrentSymbol = UseCode.Substring(j, 1)
'Check to ensure that it's a valid character
'per our encoding hashtable we defined earlier
If Not IsNothing(_encoding(CurrentSymbol)) Then
'Create a new rendered version of the character per our
'hashtable with valid values (don't read it,
'it will be encoded -- look above at the HT)
Dim EncodedSymbol As String = _encoding(CurrentSymbol).ToString
'Progress throughout the entire encoding value of this character
For i As Short = 0 To CShort(EncodedSymbol.Length - 1)
'Extract the current encoded character value from
'the complete rendering of this character (it's getting deep, right?)
Dim CurrentCode As String = EncodedSymbol.Substring(i, 1)
'Change our coordinates for drawing to match the next
'position (current position plus the char. bar width)
XPosition = XPosition + getBCSymbolWidth(CurrentCode)
Next
'Now we need to "create" a whitespace as needed, and get the width
XPosition = XPosition + getBCSymbolWidth("w")
End If
Next
'Now the nice trick of division helps with centering the barcode on the canvas
XPosition = (imageWidth / 2) - (XPosition / 2)
'NOW WE GO LIVE! THIS IS WHERE WE ACTUALLY DRAW THE BARCODE BARS
'Begin at the starting area of our FINAL rendered barcode value
For j As Short = 0 To CShort(UseCode.Length - 1)
'Set our current character to the character space of the barcode
CurrentSymbol = UseCode.Substring(j, 1)
'Check to ensure that it's a valid character per our encoding
'hashtable we defined earlier
If Not IsNothing(_encoding(CurrentSymbol)) Then
'Create a new rendered version of the character per our
'hashtable with valid values (don't read it,
'it will be encoded -- look above at the HT)
Dim EncodedSymbol As String = _encoding(CurrentSymbol).ToString
'Progress throughout the entire encoding value of this character
For i As Short = 0 To CShort(EncodedSymbol.Length - 1)
'Extract the current encoded character value from
'the complete rendering of this character (it's getting deep, right?)
Dim CurrentCode As String = EncodedSymbol.Substring(i, 1)
'Use our drawing graphics object on the canvase to create
'a bar with out position and values based
'on the current character encoding value
g.FillRectangle(getBCSymbolColor(CurrentCode), XPosition, _
YPosition, getBCSymbolWidth(CurrentCode), _barHeight)
'Lets disect this a little to see how it actually works, want to?
' getBCSymbolColor(CurrentCode)
' We already know, but this gets the color of the bar,
' either white or colorized (in this case, black)
' XPosition, YPosition
' Again, we already know -- but this is the coordinates
' to draw the bar based on previous locations
' getBCSymbolWidth(CurrentCode)
' This is the important part, we get the correct width
' (either narrow or wide) for this character (post encoding)
' _barHeight
' This is static as defined earlier, it doesn't much
' matter but it also depends on your Barcode reader
'Change our coordinates for drawing to match the next position
'(current position plus the char. bar width)
XPosition = XPosition + getBCSymbolWidth(CurrentCode)
Next
'Now we need to "ACTUALLY" create
'a whitespace as needed, and get the width
g.FillRectangle(getBCSymbolColor("w"), XPosition, _
YPosition, getBCSymbolWidth("w"), _barHeight)
'Change our coordinates for drawing to match the next position
'(current position plus the char. bar width)
XPosition = XPosition + getBCSymbolWidth("w")
Else
'This is our fallback, if it's not a valid
'character per our hashtable in C39, discard!
invalidCharacter = True
End If
Next
'As we set it above (if needed) for an invalid character
'(not allowed by the C39 guide), then we handle it here
If invalidCharacter Then
'Just fill the whole canvas white
g.FillRectangle(Brushes.White, 0, 0, imageWidth, imageHeight)
'What's the deal? Tell them! It's not right, so we can't do it -- here is why.
g.DrawString("Invalid Charachers Detected", _
New Font("Tahoma", 8), New SolidBrush(Color.Red), 0, 0)
g.DrawString("- Barcode Not Generated -", _
New Font("Tahoma", 8), New SolidBrush(Color.Black), 0, 10)
g.DrawString(Code, New Font("Tahoma", 8, FontStyle.Italic), _
New SolidBrush(Color.Black), 0, 30)
End If
'Create a new memorystream to use with our function return
Dim ms As New IO.MemoryStream
'Setup the encoding quality of the final barcode rendered image
Dim encodingParams As New EncoderParameters
encodingParams.Param(0) = New EncoderParameter(Encoder.Quality, 100)
'Define the encoding details of "how" for the image
'We will use PNG because, well it's got the best image quality for it's footprint
Dim encodingInfo As ImageCodecInfo = FindCodecInfo("PNG")
'Save the drawing directly into the stream
b.Save(ms, encodingInfo, encodingParams)
'Clean-up! Nobody likes a possible memory leaking application!
g.Dispose()
b.Dispose()
'Finally, return the image via the memorystream
Return ms
End Function
This is where we set the encoding for the image before we send it to the returned memory stream:
'Find the encoding method in the codec list
'on the computer based on the known-name (PNG, JPEG, etc)
Protected Overridable Function FindCodecInfo(ByVal codec As String) As ImageCodecInfo
Dim encoders As ImageCodecInfo() = ImageCodecInfo.GetImageEncoders
For Each e As ImageCodecInfo In encoders
If e.FormatDescription.Equals(codec) Then Return e
Next
Return Nothing
End Function
#End Region
Now, we move onto actually printing the barcode, for both the physical printing and the on-screen printing...
#Region "Printing Methods (Physical Printing and On-Screen Printing)"
'PHYSICAL PRINTING
'This is a method that just basically sends the current barcode
'renderings to the printer under the printing options
Public Sub doPrintActive()
m_PrintDocument = New Printing.PrintDocument
m_PrintDocument.PrinterSettings = PrintDialog1.PrinterSettings
m_PrintDocument.DefaultPageSettings.Color = False
m_PrintDocument.DefaultPageSettings.Margins = _
New System.Drawing.Printing.Margins(8.5, 8.5, 35, 35)
m_PrintDocument.Print()
End Sub
Private Sub m_PrintDocument_PrintPage(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintPageEventArgs) _
Handles m_PrintDocument.PrintPage
'Dim x As Integer = e.MarginBounds.X + _
' (e.MarginBounds.Width - barcodeCanvas.Width) \ 2
'Dim y As Integer = e.MarginBounds.Y + _
' (e.MarginBounds.Height - barcodeCanvas.Height) \ 2
Dim x As Integer = e.MarginBounds.X
Dim y As Integer = e.MarginBounds.Y
e.Graphics.DrawImage(barcodeCanvas, x, y)
e.HasMorePages = False
End Sub
'LOGICAL/ON-SCREEN PRINTING
'This is an extended method that we call when we want
'to generate the barcodes and display them, or print them
Public Sub doPrintNow()
'Set our current page counter and determine the total pages to be printed
curPage = 0
'This depends on whether we are printing a box label or a document label because...
' BOX Labels
' We only need one label, so we can print the whole sheet with unique labels
' The Avery 8167 labels have 80 labels per sheet
' DOC Labels
' We need TWO labels per document (one for the document,
' and one for the chain-of-custody log)
' Since the Avery 8167 paper has 80 labels, we want
' to print one unique label per two items horizontal
' This means that we will print like this...
' |LABEL 1| |LABEL 1| |LABEL 21| |LABEL 21|
' |LABEL 2| |LABEL 2| |LABEL 22| |LABEL 22|
If boxNumber.Enabled = True Then
totalPages = (CInt(bcEnd.Text) - (CInt(bcStart.Text) + 1)) / 40
Else
totalPages = (CInt(bcEnd.Text) - (CInt(bcStart.Text) + 1)) / 80
End If
'Set our toolstrip status text
ToolStrip_StatusLabel.Text = "Generating barcodes..."
'If it appears this printing session will not be effecient,
'alert the user before we just "continue"
If NotEffecientLabel.Visible Then
Dim surePrint As MsgBoxResult = _
MsgBox("It appears this label printing session isn't effecient!" & _
Chr(13) & Chr(13) & "Are you sure you would like to continue?", _
MsgBoxStyle.Information + MsgBoxStyle.YesNo, Me.Text)
If surePrint = MsgBoxResult.No Then
Exit Sub
End If
End If
'Declare the current barcode holding variable
'and the current barcode render object
Dim barcode As String
Dim thisBarCode As Bitmap
'Define a new barcode canvas drawing object with a 8.5" x 11"
'A4 paper (around there -- we add padding later)
'barcodeCanvas = New Bitmap(1275, 1650)
barcodeCanvas = New Bitmap(766, 960)
'Create our trusty graphics object for this canvas
Dim dc As Graphics = Graphics.FromImage(barcodeCanvas)
'Make it white! (the background of the canvas)
dc.Clear(Color.White)
'Declare our placeholders for coordinates used on drawing the barcode object
Dim pgX As Integer = 0
Dim pgXc As Integer = 0
Dim pgY As Integer = 0
'Declare our counter so we can apply various actions at different levels
Dim newColCounter As Integer = 1
Dim i As Integer
'Remember, if "BoxNumber" is enabled,
'then we are printing a DOCUMENT label, if not -- it's a BOX
If boxNumber.Enabled = True Then
'IT IS A DOCUMENT LABEL
'Loop through however many labels the user requested
For i = CInt(bcStart.Text) To CInt(bcEnd.Text)
'Set our status label again with the "status" and the completion progress
ToolStrip_StatusLabel.Text = "Generating Barcodes " & i & _
" (" & Math.Round((i / CInt(bcEnd.Text)) * 100, 0) & "%)..."
'Define a variable to hold our box number, and our page number
Dim bid As String = "0"
Dim pid As String = "0"
'Determine the boxnumber and preceed it with zeros
'if needed, we want it to occupy 4 spaces so
'We will always have a consistent width on the barcode
'(just, I don't know (desire for perfection maybe?) -- you will see)
If Len(boxNumber.Text) < 4 Then
Select Case 4 - Len(boxNumber.Text)
Case 1
bid = "0" & boxNumber.Text
Case 2
bid = "00" & boxNumber.Text
Case 3
bid = "000" & boxNumber.Text
End Select
Else
bid = boxNumber.Text
End If
'Do the same thing for the page number
'(well, techically not page number -- but document ID)
If Len(CStr(i)) < 4 Then
Select Case 4 - Len(CStr(i))
Case 1
pid = "0" & CStr(i)
Case 2
pid = "00" & CStr(i)
Case 3
pid = "000" & CStr(i)
End Select
Else
pid = CStr(i)
End If
'Set the barcode "code" with what we created
barcode = bid & "-" & pid
'Request that the barcode be rendered and exported
'via memorystream into our new barcode holder
thisBarCode = New Bitmap(GenerateBarcodeImage(169, 48, barcode))
'Draw the barcode onto the barcode printing page canvas
dc.DrawImage(thisBarCode, New PointF(pgX, pgY))
'Increase our X coordinates, since we need
'to draw another EXACT label to the right
pgX = pgX + (169 + 30)
'Draw it again at the new position
dc.DrawImage(thisBarCode, New PointF(pgX, pgY))
'Reset the X position and drop down a single label instance
pgY = pgY + 48
pgX = pgXc
'If we have filled a column of the label page, we need to...
If newColCounter = 20 Then
'Move to the third column (because we occupy 2 columns with DOC labels)
pgXc = (165 * 2) + (32.5 * 2)
'Reset the Y position and save the X constant variable
pgY = 0
pgX = pgXc
End If
'Update our current view within the application with what we have so far
PictureBox1.Image = barcodeCanvas
'If we have filled the entire page and there *ARE* more
'labels that need to be drawn, we need to make a new page... but not before
'Printing this current page (if the user has requested it),
'else we will lose what we just did!
If newColCounter = 40 And CInt(bcEnd.Text) > i Then
'Update the current page counter
curPage = curPage + 1
'Update the progress bar
printingProgressBar.Visible = True
printingProgressBar.Maximum = totalPages
printingProgressBar.Value = curPage
Me.Refresh()
Application.DoEvents()
'Check to see if the user wants us to print the labels or not
If printLabels.Checked Then
'Yep, they sure do! So do it!
ToolStrip_StatusLabel.Text = "Printing Label Page " & _
curPage & " (" & _
Math.Round((curPage / totalPages)) * 100 & "%)..."
Me.Refresh()
Application.DoEvents()
doPrintActive()
End If
'Start a new page and continue on...
dc.Clear(Color.White)
'Reset the coordinates for the new page
pgXc = 0
pgY = 0
pgX = pgXc
'Reset our column counter as well
newColCounter = 0
End If
'Increase the column counter
newColCounter = newColCounter + 1
Next
Else
'IT IS A BOX LABEL
'Just refer to the above comments, if there
'is anything different I will point it out here
For i = CInt(bcStart.Text) To CInt(bcEnd.Text)
ToolStrip_StatusLabel.Text = "Generating Barcodes " & _
i & " (" & Math.Round((i / CInt(bcEnd.Text)) * 100, 0) & "%)..."
'Since this is a BOX label, we don't need to determine the document ID
Dim pid As String = "0"
If Len(CStr(i)) < 4 Then
Select Case 4 - Len(CStr(i))
Case 1
pid = "0" & CStr(i)
Case 2
pid = "00" & CStr(i)
Case 3
pid = "000" & CStr(i)
End Select
Else
pid = CStr(i)
End If
'A little different code format for this one
barcode = pid
thisBarCode = New Bitmap(GenerateBarcodeImage(169, 48, barcode))
dc.DrawImage(thisBarCode, New PointF(pgX, pgY))
'You can see we aren't drawing two of them now,
'we are just dropping straight down and moving on
pgY = pgY + 48
pgX = pgXc
'Now we have different numbers based on wheter
'we are on one column, two, three, or the last
If newColCounter = 20 Then
pgXc = 165 + 32.5
pgY = 0
pgX = pgXc
End If
If newColCounter = 40 Then
pgXc = (165 * 2) + (32.5 * 2)
pgY = 0
pgX = pgXc
End If
If newColCounter = 60 Then
pgXc = (165 * 3) + (32.5 * 3)
pgY = 0
pgX = pgXc
End If
'Update the current view of the barcodes page
PictureBox1.Image = barcodeCanvas
'The page is full -- and we have more,
'if we get to this conditional and it's true
If newColCounter = 80 And CInt(bcEnd.Text) > i Then
curPage = curPage + 1
printingProgressBar.Visible = True
printingProgressBar.Maximum = totalPages
printingProgressBar.Value = curPage
Me.Refresh()
Application.DoEvents()
'If we need to print, do it!
If printLabels.Checked Then
ToolStrip_StatusLabel.Text = "Printing Label Page " & _
curPage & " (" & _
Math.Round((curPage / totalPages)) * 100 & "%)..."
Me.Refresh()
Application.DoEvents()
doPrintActive()
End If
'Clear it and start over.
dc.Clear(Color.White)
pgXc = 0
pgY = 0
pgX = pgXc
newColCounter = 0
End If
'Increase column counter
newColCounter = newColCounter + 1
Next
End If
'Lastly, since we are on the last page -- if we need to print -- do it!
If printLabels.Checked Then
ToolStrip_StatusLabel.Text = "Printing Label Page " & curPage & _
" (" & Math.Round((curPage / totalPages)) * 100 & "%)..."
Me.Refresh()
doPrintActive()
End If
'We're finished, so update the interface!
ToolStrip_StatusLabel.Text = "Finished (idle)"
printingProgressBar.Visible = False
'Start the timer to return to the box scanning area
returnToBoxScanTimer.Start()
returnToBoxScanPanel.Visible = True
End Sub
#End Region
We calculate the page requirements (physical pages of labels) to print the barcodes, with the code below. We then write it out to the user for review, and warn them if need be.
#Region "Label Pages Requirement Calculation System"
'This is what we call when we want to know how
'many pages of labels it will take to print our barcodes
Public Sub calculatePages()
'We can't calculate if the starting and ending point is nothing usable...
If bcStart.Text.Length < 1 Or bcStart.Text.Length < 1 Or _
bcEnd.Text.IsNullOrEmpty(bcEnd.Text) = True Or _
bcStart.Text.IsNullOrEmpty(bcStart.Text) = True Then
Exit Sub
End If
'Determine the page allocation limit based on BOX of DOC assignment
Dim pageAllocation As Integer = 40
If boxNumber.Enabled = False Then
pageAllocation = 80
End If
'Set the total pages initial amount to how many based on the allocation limit
Dim tpages As Double = Math.Round((CDbl(bcEnd.Text) - _
CDbl(bcStart.Text) + 1) / pageAllocation, 2)
pageUsageLabel.Text = tpages & " label pages"
'If we are over normal pages then we need to make this a non-effecient print
' Yes, there are probably many other and possibly
'better ways to check for a remainder, but this is how I wanted to do it
If CStr(tpages).Contains(".") Then
'We're over our limit, but how much?
Dim ovr As Double = CDbl(CStr(tpages).Split(".")(1))
'Just check to make sure localization didn't
'add the decimal even for a non-remaining number
If ovr > 0 Then
'Set our non-effecient warning
NotEffecientLabel.Visible = True
YesEffecientLabel.Visible = False
'Give the user more information on fixining the issue,
'so determine a low and high page that is effecient
Dim useL As Integer = 0
For useL = CDbl(bcEnd.Text) To CDbl(bcEnd.Text) + pageAllocation
If CStr(Math.Round((CDbl(useL) - CDbl(bcStart.Text) + 1) / _
pageAllocation, 2)).Split(".").Length = 1 Then
Exit For
End If
Next
Dim useH As Integer = 0
For useH = CDbl(bcEnd.Text) - (pageAllocation - 1) To _
CDbl(bcEnd.Text) + pageAllocation
If CStr(Math.Round((CDbl(useH) - CDbl(bcStart.Text) + 1) / _
pageAllocation, 2)).Split(".").Length = 1 Then
Exit For
End If
Next
'Write out what they can use you have an even number of pages
NotEffecientLabel.Text = "Not Effecient (Use " & _
useH & " or " & useL & " instead)"
Else
'We are effecient! Great job "user"!
NotEffecientLabel.Visible = False
YesEffecientLabel.Visible = True
End If
Else
'Yes! Yes! Yes! -- you get it.
NotEffecientLabel.Visible = False
YesEffecientLabel.Visible = True
End If
End Sub
'Calculate the page requirements when they change counts
Private Sub bcStart_TextChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles bcStart.TextChanged
calculatePages()
End Sub
Private Sub bcEnd_TextChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles bcEnd.TextChanged
calculatePages()
End Sub
#End Region
While the main form loads, we will load the hashtable with the encoding values, among other things:
'Do the pre-load events for when this form is up
Private Sub mainBarcodeWorkspace_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
'Generate the hashtable of encoding values
ITS_BarcodeC39()
'Do initial calculations of pages required to print
calculatePages()
'Focus on the box number, it's primarly the most important in most cases
boxNumber.Focus()
'Set our global position in memory in our module
mainFrm = Me
'Show the box scanning form
boxScanFrm.ShowDialog(Me)
End Sub
End Class
Points of Interest
This was a very fun and interesting project to tackle. I've learned a lot more about GDI+ and have an overall knowledge of the .NET framework from this project. As with every project, there are problems that arise, but all can be solved with a clear head and time to think!
History
- Initial release - 03/19/2009, 12:40 AM CST.
- Version 2.0 release - 03/20/2009, 10:49 PM CST.