Alessandro Del Sole's Blog

{ A programming space about Microsoft® .NET® }
posts - 1887, comments - 2047, trackbacks - 352

My Links

News

Your host

This is me! Questo spazio è dedicato a Microsoft® .NET®, di cui sono molto appassionato :-)

Cookie e Privacy

Disabilita cookie ShinyStat

Microsoft MVP

My MVP Profile

Microsoft Certified Professional

Microsoft Specialist

Il mio libro su VB 2015!

Pre-ordina il mio libro su VB 2015 Pre-ordina il mio libro "Visual Basic 2015 Unleashed". Clicca sulla copertina per informazioni!

Il mio libro su WPF 4.5.1!

Clicca sulla copertina per informazioni! E' uscito il mio libro "Programmare con WPF 4.5.1". Clicca sulla copertina per informazioni!

These postings are provided 'AS IS' for entertainment purposes only with absolutely no warranty expressed or implied and confer no rights.
If you're not an Italian user, please visit my English blog

Le vostre visite

I'm a VB!

Guarda la mia intervista a Seattle

Follow me on Twitter!

Altri spazi

CodePlex download Scarica i miei progetti open-source su CodePlex!

Article Categories

Archives

Post Categories

Image Galleries

Privacy Policy

Visual Studio LightSwitch: acquisizione di immagini da scanner con WIA e VB 2010

L'estendibilità di Visual Studio LightSwitch e il fatto di essere basato su Silverlight 4 sono due fattori che permettono di fare delle cose incredibili, quindi anche di sopperire a quelle funzionalità che non ci sono di default.

Oggi vediamo come sia possibile ricorrere alla COM Automation di Silverlight 4 per scannerizzare immagini da un'applicazione LightSwitch.

Da premettere: COM Automation significa elevati privilegi, quindi utilizzabilità solo se l'applicazione gira come client desktop, fuori dal browser.

Detto questo, creiamo un nuovo progetto LightSwitch in Visual Basic (o C# se preferite, ma il codice che mostro è VB ).

Non aggiungiamo alcunché, giusto per finalità dimostrative. Creiamo semplicemente un nuovo screen di tipo data entry, chiamandolo Scanner Screen:

Quando lo screen è stato aggiunto, aggiungiamo un pulsante che ci permetterà di lanciare l'azione di scansione. Quindi nello Screen Designer espandiamo la Screen Command Bar, quindi click su Add -> Button, quindi specifichiamo il nome per il pulsante, ad esempio Scan:

Ora le possibilità sono due: o mettiamo il codice che ci serve direttamente nello screen, oppure facciamo una cosa più sensata e lo mettiamo in una library separata che potremo poi gestire in modo migliore, staccandola da LightSwitch. Quindi:

  1. Aggiungiamo alla Solution un nuovo progetto di tipo Silverlight Class Library, per Silverlight 4
  2. Rinominiamo il file Class1.vb in ScannerService.vb
  3. Nel progetto LightSwitch, tramite l'apposito pulsante in Solution Explorer attiviamo la visualizzazione di tipo File View
  4. Tasto destro sul progetto chiamato Client, quindi Add Reference e aggiungiamo un riferimento al progetto Silverlight appena creato. Si può fare anche dopo la scrittura del codice, ma così non ci dimentichiamo

Per fare la scansione ricorriamo alle API Windows Imaging Acquisition (WIA), che ci permettono di interagire con periferiche di acquisizione tramite COM Automation. Ci sono possibilità molto più complesse con le WIA, anche di gestione dei formati di acquisizione, quello che vi mostro è il più semplice. Ecco il codice completo della classe:

'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

Si lavora in late-binding quando si ricorre alla COM Automation, di conseguenza in VB impostiamo Option Strict Off mentre se usiamo C# ricorriamo alla keyword dynamic. Alcuni commenti:

  • se AutomationFactory.IsAvailable è False, vuol dire che l'applicazione è in-browser quindi senza privilegi elevati, quindi esce
  • si ottengono i riferimenti necessari agli oggetti COM delle WIA
  • se il risultato della scansione è positivo, il file viene salvato in una cartella specificata. In questo esempio il nome del file viene composto generando un GUID, ma è a proprio piacimento

Impostare due eventi ci permette di capire da LightSwitch il momento in cui l'acquisizione è completa o è fallita.

Tornando proprio a LightSwitch, nello Screen Designer tasto destro sul pulsante da noi creato, quindi Edit Execute Code. Ecco il codice che gestisce il pulsante:

        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 successful")
                                                     End Sub
 
            scanner.Scan()
        End Sub

Si noti l'utilizzo delle statement lambda di VB 2010 per i gestori di evento, invece degli AddressOf. Avviando l'applicazione, dapprima vediamo come il pulsante sia visibile nell'unico screen che abbiamo creato:

Al click sul pulsante, si osserva come la finestra di dialogo per l'acquisizione da scanner venga mostrata correttamente:

Nel momento in cui viene avviata la scansione, LightSwitch capisce che il thread della UI viene impegnato e quindi mostra un messaggio di attesa anche se non gliel'abbiamo detto :

Notate, infine, come l'aver implementato, e successivamente intercettato, un evento ci abbia permesso di mostrare un messaggio all'utente:

Ed ecco il risultato della scansione:

Finito? in teoria si, in pratica possiamo fare una finezza. Poiché la classe AutomationFactory è raggiungibile anche lato LightSwitch, possiamo sfruttarla per gestire il CanExecute del pulsante di modo che sia attivo solo se l'applicazione ha i permessi richiesti. Nello Screen Designer, right-click sul pulsante -> Edit CanExecute Code. Una riga di codice:

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

A questo punto il pulsante sarà attivo solamente se l'applicazione gira come desktop client, altrimenti sarà disabilitato.

Abbiamo quindi imparato un altro modo per estendere LightSwitch con una funzionalità molto interessante e spesso importante nelle applicazioni gestionali moderne. Con un po' più di sforzo e fantasia non è complicato associare l'immagine ottenuta a un qualche campo di tabella.

Alessandro

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

Powered by:
Powered By Subtext Powered By ASP.NET