ByteScout Barcode Reader SDK – VB.NET – Read From Live Video Cam (WPF)

  • Home
  • /
  • Articles
  • /
  • ByteScout Barcode Reader SDK – VB.NET – Read From Live Video Cam (WPF)

ByteScout Barcode Reader SDK – VB.NET – Read From Live Video Cam (WPF)

Application.xaml.vb

Class Application

    ' Application-level events, such as Startup, Exit, and DispatcherUnhandledException
    ' can be handled in this file.

End Class

MainWindow.xaml.vb

Imports System.ComponentModel
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.IO
Imports System.Reflection
Imports System.Threading
Imports System.Windows.Threading
Imports Bytescout.BarCodeReader
Imports TouchlessLib

Public Class MainWindow

    ' Touchless lib manager object (to use it you should have TouchlessLib.dll and WebCamLib.dll)
    Private _touchlessMgr As TouchlessMgr

    ' USED IN POPUP MODE ONLY (see ShowScanPopup() method)
    ' Close or not on the first barcode found
    ' (results are saved in m_foundBarcodes)
    Public Property CloseOnFirstBarcodeFound As Boolean = False

    ' Indicates if the form is closed
    Public Property IsClosed As Boolean = False

    ' Background processing object
    Private _backgroundWorker As New BackgroundWorker()

    ' Barcode type to scan
    Private _barcodeTypeToFind As New BarcodeTypeSelector()

    ' Array with decoded barcodes from the last scanning session.
    Public Property FoundBarcodes As FoundBarcode() = Nothing

    ' Scanning delay (ms); default is to scan every 800 ms.
    Const ScanDelay As Integer = 800

    ' Internal varaible to indicate the status.
    Public Shared Status As Boolean = True

    Public Sub New()

        InitializeComponent()

        lblScanning.Visibility = Visibility.Collapsed

        _backgroundWorker.WorkerSupportsCancellation = True
        AddHandler _backgroundWorker.DoWork, AddressOf BackgroundWorker_DoWork
        AddHandler _backgroundWorker.RunWorkerCompleted, AddressOf BackgroundWorker_RunWorkerCompleted

    End Sub

    Delegate Sub MyDelegate()

    ' Searches for barcodes in bitmap object
    Private Function FindBarcodes(bitmap As Bitmap) As FoundBarcode()

        Dim reader As New Bytescout.BarCodeReader.Reader()

        Try
            reader.RegistrationName = "demo"
            reader.RegistrationKey = "demo"

            Me.Dispatcher.Invoke(DispatcherPriority.Normal, Sub() UpdateBarcodeTypeToFindFromCombobox())

            reader.BarcodeTypesToFind = _barcodeTypeToFind

            Dim result As FoundBarcode() = reader.ReadFrom(bitmap)
            Dim timeNow As String = String.Format("{0:HH:mm:ss:tt}", DateTime.Now)

            Dispatcher.Invoke(DispatcherPriority.Normal,
                              Sub()
                                  If result IsNot Nothing And result.Length > 0 Then
                                      textAreaBarcodes.SelectAll()
                                      textAreaBarcodes.Selection.Text = Environment.NewLine & "Time: " & timeNow & Environment.NewLine

                                      ' insert barcodes into text box
                                      For Each barcode As FoundBarcode In result
                                          ' make a sound that we found the barcode
                                          Console.Beep()
                                          'form the string with barcode value
                                          Dim barcodeValue As String = String.Format("Found: {0} {1}" & Environment.NewLine, barcode.Type, barcode.Value)
                                          ' add barcode to the text area output
                                          textAreaBarcodes.AppendText(barcodeValue & Environment.NewLine)
                                          ' add barcode to the list of saved barcodes
                                          lblFoundBarcodes.Content = String.Format("Found {0} barcodes:", result.Length)
                                      Next
                                  End If

                                  ' make "Scanning..." label flicker
                                  If lblScanning.Visibility = Visibility.Collapsed Then
                                      lblScanning.Visibility = Visibility.Visible
                                  Else
                                      lblScanning.Visibility = Visibility.Collapsed
                                  End If
                              End Sub)
            ' return found barcodes
            Return result

        Finally
            reader.Dispose()
        End Try

    End Function

    ' Updates barcode type filter according with combobox selection
    Private Sub UpdateBarcodeTypeToFindFromCombobox()

        Dim selectedItemText As String = cbBarCodeType.Text

        If String.IsNullOrEmpty(selectedItemText) Then Throw New Exception("Empty barcode type selection.")

        _barcodeTypeToFind.Reset()

        ' Iterate through BarcodeTypeSelector bool properties 
        ' and enable property by barcode name selected in the combobox
        For Each propertyInfo As PropertyInfo In GetType(BarcodeTypeSelector).GetProperties()

            ' Skip readonly properties
            If Not propertyInfo.CanWrite Then
                Continue For
            End If

            If propertyInfo.Name = selectedItemText Then
                propertyInfo.SetValue(_barcodeTypeToFind, True, Nothing)
            End If
        Next

    End Sub

    Private Sub Window_Loaded(sender As System.Object, e As RoutedEventArgs) Handles MyBase.Loaded

        'Populate barcode types into the combobox
        PopulateBarcodeTypesCombobox()

        InitCamera()

        StartDecoding()

    End Sub

    Private Sub InitCamera()

        Try
            ' Create Touchless lib manager to work with video camera
            _touchlessMgr = New TouchlessMgr()

            ' Iterate through available video camera devices
            For Each camera As Camera In _touchlessMgr.Cameras
                ' Add to list of available camera devices
                cbCamera.Items.Add(camera)
            Next

            ' Select first available camera
            cbCamera.SelectedItem = _touchlessMgr.Cameras(0)

            ' Setting default image dimensions; see also camera selection event.
            _touchlessMgr.Cameras(0).CaptureWidth = Integer.Parse(tbCameraWidth.Text)
            _touchlessMgr.Cameras(0).CaptureHeight = Integer.Parse(tbCameraHeight.Text)

        Catch exception As Exception
            MessageBox.Show("No video camera available. Please connect camera." + Environment.NewLine + exception.Message)
        End Try

    End Sub

    Sub StartDecoding()

        UpdateCameraSelection()

        ' Clear the text box output
        Dim txt As New TextRange(textAreaBarcodes.Document.ContentStart, textAreaBarcodes.Document.ContentEnd)
        txt.Text = ""

        ' Clean list of found barcodes
        FoundBarcodes = Nothing

        ' Check camera selected
        If cbCamera.SelectedIndex <> -1 Then

            ' Set status
            Status = True

            ' Update UI buttons
            btnStart.IsEnabled = False
            btnStop.IsEnabled = True
            cbBarCodeType.IsEnabled = False
            cbCamera.IsEnabled = False
            tbCameraHeight.IsEnabled = False
            tbCameraWidth.IsEnabled = False
            lblScanning.Content = "Scanning..."

            ' Start the decoding thread
            _backgroundWorker.RunWorkerAsync(CloseOnFirstBarcodeFound)

        Else
            MessageBox.Show("Please select camera")
        End If

    End Sub


    Private Sub Window_Closing(sender As System.Object, e As CancelEventArgs) Handles MyBase.Closing
        Deinitialize()
    End Sub

    Private Sub cbCamera_SelectionChanged(sender As System.Object, e As SelectionChangedEventArgs) Handles cbCamera.SelectionChanged
        UpdateCameraSelection()
    End Sub

    Private Sub btnStart_Click(sender As System.Object, e As RoutedEventArgs) Handles btnStart.Click
        StartDecoding()
    End Sub

    Private Sub btnStop_Click(sender As System.Object, e As RoutedEventArgs) Handles btnStop.Click
        StopDecoding()
    End Sub

    Private Sub btnExit_Click(sender As System.Object, e As RoutedEventArgs) Handles btnExit.Click
        Close()
    End Sub

    Private Sub btnTryPopup_Click(sender As System.Object, e As RoutedEventArgs) Handles btnTryPopup.Click

        ' Stop scan if any
        StopDecoding()

        ' Deinit the current camera
        DeinitCamera()

        ShowScanPopup()

        ' Reinit current camera
        InitCamera()

    End Sub

    Sub BackgroundWorker_DoWork(sender As Object, e As DoWorkEventArgs)

        Dim worker As BackgroundWorker = sender
        Dim closeOnFirstBarcode As Boolean = e.Argument

        While True

            ' Work till user canceled the scan
            If worker.CancellationPending Then
                e.Cancel = True
                Return
            End If

            ' Get current frame bitmap from camera using Touchless lib
            Dim bitmap As Bitmap = _touchlessMgr.CurrentCamera.GetCurrentImage()

            ' Search barcodes
            Dim result As FoundBarcode() = Nothing

            If bitmap IsNot Nothing Then result = FindBarcodes(bitmap)

            ' Check if we need to stop on first barcode found
            If closeOnFirstBarcode AndAlso result IsNot Nothing AndAlso result.Length > 0 Then
                e.Result = result
                Return
            End If

            ' Wait a little to lower CPU load
            Thread.Sleep(ScanDelay)

        End While


    End Sub

    Sub BackgroundWorker_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs)

        ' Clear last results
        FoundBarcodes = Nothing

        If e.Cancelled Then
            lblScanning.Content = "Canceled"
        ElseIf e.Error IsNot Nothing Then
            lblScanning.Content = "Error: " & e.Error.Message
        Else
            lblScanning.Content = "Done."
            FoundBarcodes = e.Result
        End If

        StopDecoding()

    End Sub

    ' Update picture box with the latest frame from video camera
    Sub CurrentCamera_OnImageCaptured(sender As Object, e As CameraEventArgs)
        ' You can change image dimensions if needed
        '_touchlessMgr.CurrentCamera.CaptureWidth = 320
        '_touchlessMgr.CurrentCamera.CaptureHeight = 240
        Dispatcher.Invoke(DispatcherPriority.Normal, Sub()
                                                         If _touchlessMgr IsNot Nothing Then

                                                             pictureVideoPreview.BeginInit()
                                                             Dim imageSource As BitmapImage = BitmapToImageSource(_touchlessMgr.CurrentCamera.GetCurrentImage(), ImageFormat.Png)

                                                             Dim st = New ScaleTransform()
                                                             st.ScaleX = 320.0F / imageSource.PixelWidth
                                                             st.ScaleY = 240.0F / imageSource.PixelHeight

                                                             pictureVideoPreview.Source = New TransformedBitmap(imageSource, st)
                                                             pictureVideoPreview.EndInit()
                                                             pictureVideoPreview.UpdateLayout()

                                                         End If
                                                     End Sub)
    End Sub

    Function BitmapToImageSource(bitmap As Bitmap, imageFormat As ImageFormat) As BitmapImage

        Using memoryStream As New MemoryStream

            bitmap.Save(memoryStream, imageFormat)
            memoryStream.Position = 0

            Dim bitmapImage As New BitmapImage()
            bitmapImage.BeginInit()
            bitmapImage.StreamSource = memoryStream
            bitmapImage.CacheOption = BitmapCacheOption.OnLoad
            bitmapImage.EndInit()

            Return bitmapImage
        End Using

    End Function

    Sub StopDecoding()

        _backgroundWorker.CancelAsync()

        ' Update UI elements
        lblScanning.Visibility = Visibility.Collapsed

        ' Change working status
        Status = False

        btnStart.IsEnabled = True
        btnStop.IsEnabled = False

        cbBarCodeType.IsEnabled = True
        cbCamera.IsEnabled = True

        tbCameraHeight.IsEnabled = True
        tbCameraWidth.IsEnabled = True

        If CloseOnFirstBarcodeFound Then
            If FoundBarcodes IsNot Nothing AndAlso FoundBarcodes.Length > 0 Then
                Close()
            End If
        End If

    End Sub

    Sub UpdateCameraSelection()

        If cbCamera.Items.Count > 0 And cbCamera.SelectedIndex > -1 Then

            If _touchlessMgr.CurrentCamera IsNot Nothing Then
                RemoveHandler _touchlessMgr.CurrentCamera.OnImageCaptured, AddressOf CurrentCamera_OnImageCaptured
            End If

            _touchlessMgr.CurrentCamera = Nothing

            Dim currentCamera As Camera = _touchlessMgr.Cameras(cbCamera.SelectedIndex)

            ' Setting camera output image dimensions
            currentCamera.CaptureWidth = Integer.Parse(tbCameraWidth.Text)
            currentCamera.CaptureHeight = Integer.Parse(tbCameraHeight.Text)

            _touchlessMgr.CurrentCamera = currentCamera
            AddHandler _touchlessMgr.CurrentCamera.OnImageCaptured, AddressOf CurrentCamera_OnImageCaptured

        End If
    End Sub

    Sub PopulateBarcodeTypesCombobox()

        cbBarCodeType.Items.Clear()
        Dim items As New List(Of String)()

        For Each propertyInfo As PropertyInfo In GetType(BarcodeTypeSelector).GetProperties()
            ' Skip readonly properties
            If Not propertyInfo.CanWrite Then
                Continue For
            End If

            items.Add(propertyInfo.Name)
        Next

        items.Sort()
        cbBarCodeType.ItemsSource = items

        ' Select first item in combobox (first is "Find All")
        cbBarCodeType.SelectedItem = cbBarCodeType.Items(0)

    End Sub

    Sub Deinitialize()

        ' Cancel decoding thread
        _backgroundWorker.CancelAsync()

        ' Deinit camera
        DeinitCamera()

        ' Mark as closed
        _isClosed = True

    End Sub

    Sub DeinitCamera()

        If _touchlessMgr IsNot Nothing Then
            RemoveHandler _touchlessMgr.CurrentCamera.OnImageCaptured, AddressOf CurrentCamera_OnImageCaptured
            _touchlessMgr.CurrentCamera = Nothing
        End If

        If cbCamera.SelectedItem IsNot Nothing Then
            cbCamera.SelectedItem = Nothing
        End If

        cbCamera.Items.Clear()
        _touchlessMgr = Nothing

        Thread.Sleep(500)

    End Sub

    Sub ShowScanPopup()

        ' Create another MainWindow instance to scan barcodes
        Dim popup As New MainWindow()
        ' Set new popup position shifted by 20 pixels
        popup.Left = Left + 20
        popup.Top = Top + 20

        ' Set the new popup window to close on first found barcode
        popup.CloseOnFirstBarcodeFound = True

        ' Hide btnTryPopup button 
        popup.btnTryPopup.Visibility = Visibility.Hidden
        popup.btnStop.Visibility = Visibility.Hidden
        popup.btnStart.Visibility = Visibility.Hidden

        ' Set the popup title
        popup.Title = "POPUP DIALOG - ONE-TIME SCAN"

        ' Show the dialog
        popup.Show()

        ' Now wait while the popup is closed (it will be closed on barcode found or canceled)
        While Not popup.IsClosed
            ' HACK: Simulate "DoEvents"
            Dispatcher.Invoke(DispatcherPriority.Background, Sub() Thread.Sleep(20))
            Thread.Sleep(20)
        End While

        ' Checking if one-time scan dialog found barcodes 
        If popup.FoundBarcodes IsNot Nothing AndAlso popup.FoundBarcodes.Length > 0 Then
            MessageBox.Show("Popup scan found the barcode: " & Environment.NewLine & popup.FoundBarcodes(0).Value, "POPUP RESULT")
        Else
            MessageBox.Show("Popup canceled. Returning to the main window")
        End If

        ' Close the dialog
        popup.Close()

    End Sub

End Class

prev
next