Alessandro Del Sole's Blog

/* A programming space about Microsoft® .NET® */
posts - 159, comments - 0, trackbacks - 0

My Links

News

Your host

This is me! This space is about Microsoft® .NET® and Microsoft® Visual Basic development. Enjoy! :-)

These postings are provided 'AS IS' for entertainment purposes only with absolutely no warranty expressed or implied and confer no rights.

Microsoft MVP

My MVP Profile

I'm a VB!

Watch my interview in Seattle

My new book on VB 2015!

Pre-order VB 2015 Unleashed Pre-order my new book "Visual Basic 2015 Unleashed". Click for more info!

My new book on LightSwitch!

Visual Studio LightSwitch Unleashed My book "Visual Studio LightSwitch Unleashed" is available. Click the cover!

Your visits

Follow me on Twitter!

CodePlex download Download my open-source projects from CodePlex!

Article Categories

Archives

Post Categories

.NET Framework

Blogroll

Help Authoring

Microsoft & MSDN

Setup & Deployment

Visual Basic 2005/2008/2010

Visual Studio LightSwitch: acquiring images from devices with Visual Basic and the WIA APIs

Visual Studio LightSwitch is an extensible environment and is based upon Silverlight 4. The combination of these two factors allows creating a lot of additional stuff so that you can provide features that are not available by default.

Today the goal is understanding how to use COM Automation in Silverlight 4 to acquire images (and possibly documents) from scanners in a LightSwitch application.

Before going on, it is worth mentioning that COM Automation requires elevated privileges so this means that the application must run as a desktop client (out-of-browser).

So let's create a new LightSwitch project. I will show some Visual Basic code but translating into C# should not be difficult. For this particular demo we do not need data. We just need to create a new empty screen, for example based on the data entry template:

When the new screen is available in the designer, we can add a button to launch the scanning action. Thus in the Screen Designer expand Screen Command Bar, then click Add -> Button, then specify the name for the new button, such as Scan:

We have two alternatives at this point: we can either put the code at the screen level or (better) we can place it in a separate library that can be handled more appropriately. So:

  1. add to the solution a new project of type Silverlight Class Library, for Silverlight 4
  2. rename the file Class1.vb into ScannerService.vb
  3. in the LightSwitch project, via the specific button in Solution Explorer, enable File View
  4. right-click the Client project, then add a reference to the newly created Silverlight project. We could do this later, but it is just for our convenience

To acquire images from a scanner we use the Windows Imaging Acquisition (WIA) APIs, which allow interacting with acquisition devices via COM Automation. The way I'm going to show you is the simplest possible, but there are a lot of possibilities, including handling image acquisition format. Following is the full code for the class:

'We work in late-binding. Use the "dynamic" keyword in C#
Option Strict Off
 
Imports System.Runtime.InteropServices.Automation
 
Public Class ScannerService
    Public Event AcquisitionCompleted()
    Public Event AcquisitionFailed()
 
    Public Sub Scan()
        'If not out-of-browser:
        If AutomationFactory.IsAvailable = False Then
            RaiseEvent AcquisitionFailed()
            Exit Sub
        End If
 
        'Gets a reference to the WIA dialog
        Dim commonDialog As Object = AutomationFactory.CreateObject("WIA.CommonDialog")
 
        'Show the dialog for scanning inmages
        Dim imageFile As Object = commonDialog.ShowAcquireImage
 
        'If the result is not null,
        If imageFile IsNot Nothing Then
            'Saves the result as an image to disk
            Dim filePath As String = String.Format("C:\Temp\{0}.jpg", Guid.NewGuid)
            imageFile.SaveFile(filePath)
            RaiseEvent AcquisitionCompleted()
            commonDialog = Nothing
        End If
    End Sub
End Class

The code works in in late-binding because of COM Automation, so in VB we need to set Option Strict Off whereas in C# the keyword to use is dynamic. Some considerations:

  • if AutomationFactory.IsAvailable is False, it means that the application is running inside the browser and therefore with limited privileges, so the code just returns 
  • the code gets necessary references to COM objects for WIA
  • if the acquisition process completes successfully, the generated image file is saved into the specified folder. In the above example the file name is generated from a GUID but you can replace this behavior

Also notice that implementing two events allows understanding from the LightSwitch side the moment in which the acquisition completes or fails.

Going back to LightSwitch, in the Screen Designer right click the new button, then select Edit Execute Code. This is the code that is executed when the button is pressed:

        Private Sub Scan_Execute()
            ' Write your code here.
            Dim scanner As New SilverlightScannerLibrary.ScannerService
 
            AddHandler scanner.AcquisitionFailed, Sub()
                                                      ShowMessageBox("Acquisition failed.")
                                                  End Sub
 
            AddHandler scanner.AcquisitionCompleted, Sub()
                                                         ShowMessageBox("Acquisition completed")
                                                     End Sub
 
            scanner.Scan()
        End Sub

Notice the usage of statement lambdas of VB 2010 to handle events, instead of explicit delegates via AddressOf. If you run the application, you can first notice the new button in the screen:

When you click the button, notice how the WIA dialog for acquisition devices is shown correctly:

When the process starts, LightSwitch understands that the UI thread gets busy and therefore it shows a waiting message even if we did not write code to handle this :

Finally notice how a message is shown when the process completes. This is due to one of the events that we implemented previously:

This is the result of the acquisition process from my scanner:

There is something cool that we can do at this point. Since the AutomationFactory class can be reached from the LightSwitch side too, we can leverage it to handle the button's CanExecute so that it is enabled only if the application is running with elevated privileges. In the Screen Designer, right-click the custom button -> Edit CanExecute Code. One line of code:

        Private Sub Scan_CanExecute(ByRef result As Boolean)
            result = System.Runtime.InteropServices.Automation.AutomationFactory.IsAvailable
        End Sub

At this point the custom button will be enabled only if the application is running as a desktop client, otherwise it will get disabled.

We definitely saw another way of extending LightSwitch applications with an interesting feature. With a little more of fantasy and effort it should not be difficult to associate the acquired image to some entity field.

Alessandro

Print | posted on domenica 22 maggio 2011 20:29 | Filed Under [ Visual Basic Visual Studio LightSwitch ]

Feedback

No comments posted yet.

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 1 and 5 and type the answer here:

Powered by:
Powered By Subtext Powered By ASP.NET