Passa ai contenuti principali

Briciole di WPF : InkCanvas e gesture

In questo post vorrei farvi vedere come poter riconoscere le gesture (cioè i movimenti) che l’utente può fare con il mouse, con le dita o con un eventuale stilo utilizzando il contenitore InkCanvas.

Il controllo InkCanvas, in realtà, si può utilizzare per intercettare i “gesti” dell’utente, per disegnare, per selezionare una porzione di interfaccia o per tutte queste funzionalità contemporaneamente.

Cominciamo col dire che per poter utilizzare l’InkCanvas solo per intercettare le gesture dell’utente è necessario impostare la proprietà EditingMode con il valore InkCanvasEditingMode.GestureOnly.

L’enumerazione InkCanvasEditingMode contiene tutti i possibili comportamenti dell’InkCanvas:

  • GestureOnly : il controllo rileva le gesture. In questo caso l’utente lascia un segno sulla superficie del controllo ma questo sparisce al termine della singola gesture;
  • EraseByPoint : permette di cancellare una parte di un precedente disegno passando il pennino come una gomma;
  • EraseByStroke : permette di cancellare un’intera curva precedentemente disegnata passando il pennino come una gomma;
  • Ink : l’utente può disegnare con il pennino;
  • InkAndGesture : l’utente può disegnare ma il controllo rileva anche le gesture;
  • None : il controllo non permette di disegnare e non rileva le gesture;
  • Select : il controllo permette di selezionare una porzione della superficie del controllo.

Concentriamoci, ora su come possiamo intercettare le gesture dell’utente.

Per poter far si che il controllo InkCanvas sia in grado di intercettare le gesture dobbiamo, inizialmente impostare la sopra citata proprietà, quindi istruire il controllo stesso su quali gesture siamo intenzionati ad intercettare.

Per fare questa ultima operazione dobbiamo utilizzare il metodo SetEnabledGestures che si aspetta come argomento un oggetto IEnumerable(of ApplicationGesture).

Ad esempio potremmo scrivere:

  1. Dim gestures = {ApplicationGesture.Circle,
  2.                 ApplicationGesture.Square,
  3.                 ApplicationGesture.Triangle}
  4. inkCanvas.SetEnabledGestures(gestures)

per istruire il controllo a rilevare i cerchi, i quadrati e i triangoli descritti dall’utente. Attenzione che, se non eseguiamo il metodo SetEnabledGestures

Istruito il controllo dobbiamo preoccuparci di gestire l’evento Gesture che è l’evento scatenato dal controllo ogni qual volta l’utente appoggia, muove e rilascia il pennino sulla superficie del controllo.
Dobbiamo subito precisare che tale evento viene scatenato sempre, per qualsiasi gesture dell’utente (anche se non è una di quelle per cui abbiamo istruito il controllo).

L’evento Gesture mette a disposizione, come argomento un oggetto di tipo InkCanvasGestureEventArgs, derivato da RoutedEventArgs, dal quale possiamo ricavare o l’insiame delle linee disegnate dall’utente (tramite la proprietà Strokes) oppure far riconoscere al framework quali sono state le gesture che l’utente ha tentato di eseguire.

Il primo caso è da utilizzare quando vogliamo interpretare, con un nostro algoritmo, le gesture dell’utente; il secondo caso, invece, delega al framework il riconoscimento rendendoci la vita più semplice.

Per recuperare l’elenco delle gesture interpretate dal framework possiamo utilizzare il metodo GetGestureRecognitionResults() della classe InkCanvasGestureEventArgs.
Questo metodo restituisce una collezione (sola lettura) di oggetti GestureRecognitionResult.

La classe GestureRecognitionResult contiene le informazioni relative alle gesture, ed in particolare possiamo utilizzare le due proprietà RecognitionConfidence e ApplicationGesture per capire esattamente quale gesture sono state eseguite dall’utente.

RecognitionConfidence è un enumerazione che può assumere i seguenti valori Poor, Intermediate e Strong ed indica la “precisione” con cui il framework ha interpretato la gesture.

ApplicationGesture, infine, contiene la gesture riconosciuta (se è una di quelle per cui il controllo è stato istruito) oppure NoGesture se la gesture non è riconosciuta.

Per testare il meccanismo di riconoscimento delle gesture ho preparato una semplice applicazione WPF che contiene un InkCanvas, un elenco di checkbox per selezionare le gesture da riconoscere, un livello minimo di riconoscimento delle gesture e un’area (costituita da un TextBlock) in cui verrà scritta la gesture eventualmente riconosciuta.

Il layout dell’applicazione è il seguente:

Layout_Applicazione_GestureIn questa window possiamo selezionare per quali gesture “istruire” l’InkCanvas e quale è il livello minimo desiderato di precisione della gesture.

In particolare, nel momento in cui selezioniamo (o deselezioniamo) una delle gesture mostrate nella lista di destra, viene richiamato il seguente codice:

  1. Private Sub AddApplicationGestures()
  2.     Me.inkCanvas.EditingMode = InkCanvasEditingMode.GestureOnly
  3.  
  4.     Dim gestures = (From c In Me.pnlGestureOptions.Children.OfType(Of Control)()
  5.                     Where TypeOf (c) Is CheckBox AndAlso CType(c, CheckBox).IsChecked
  6.                     Select CType(c.Tag, ApplicationGesture)).ToList()
  7.  
  8.     If gestures.Count = 0 Then
  9.         gestures.Add(ApplicationGesture.NoGesture)
  10.     End If
  11.     Me.inkCanvas.SetEnabledGestures(gestures)
  12.  
  13. End Sub

Il precedente metodo ricava i valori delle gestures dei CheckBox selezionati nel pannello di destra tramite una query LINQ e utilizza il metodo SetEnableGestures() per impostarli sul controllo InkCanvas. Se nessun CheckBox è selezionato (nessuna gesture) allora viene impostato il valore “NoGesture”.

Quando l’utente disegna una linea nell’InkCanvas, il controllo genera l’evento Gesture nel quale andiamo a verificare che l’utente abbia disegnato una delle gesture da noi selezionate:

  1. Private Sub inkCanvas_Gesture(ByVal sender As System.Object, ByVal e As System.Windows.Controls.InkCanvasGestureEventArgs)
  2.     Dim gestureResults As ReadOnlyCollection(Of GestureRecognitionResult)
  3.     gestureResults = e.GetGestureRecognitionResults()
  4.  
  5.     For Each gesture In gestureResults
  6.         If gesture.ApplicationGesture <> ApplicationGesture.NoGesture Then
  7.             If optPoor.IsChecked And gesture.RecognitionConfidence = RecognitionConfidence.Poor Then
  8.                 Me.txtResult.Background = New SolidColorBrush(Color.FromRgb(0, 255, 255))
  9.                 Me.txtResult.Text = gesture.ApplicationGesture.ToString()
  10.                 Exit For
  11.             End If
  12.             If optIntermediate.IsChecked And gesture.RecognitionConfidence = RecognitionConfidence.Intermediate Then
  13.                 Me.txtResult.Background = New SolidColorBrush(Color.FromRgb(255, 255, 255))
  14.                 Me.txtResult.Text = gesture.ApplicationGesture.ToString()
  15.                 Exit For
  16.             End If
  17.             If optStrong.IsChecked And gesture.RecognitionConfidence = RecognitionConfidence.Strong Then
  18.                 Me.txtResult.Background = New SolidColorBrush(Color.FromRgb(0, 255, 0))
  19.                 Me.txtResult.Text = gesture.ApplicationGesture.ToString()
  20.                 Exit For
  21.             End If
  22.         Else
  23.             Me.txtResult.Background = New SolidColorBrush(Color.FromRgb(255, 0, 0))
  24.             Me.txtResult.Text = gesture.ApplicationGesture.ToString()
  25.         End If
  26.     Next
  27. End Sub

Se la gesture è riconosciuta (ed ha, al minimo, il livello di precisione da noi selezionato) viene visualizzato il relativo valore con un opportuno colore (in base alla precisione), altrimenti viene visualizzato NoGesture.

L’applicazione mostrata è molto semplice ed inutile, ma può mostrare come interagire con l’InkCanvas per eseguire operazioni quando l’utente esegue particolari gesture.

Per scaricare i sorgenti della soluzione di prova (Visual Studio 2010) cliccare sull’icona seguente:

Commenti

Post popolari in questo blog

VB.NET: Convertire un file DOC in RTF e PDF con office interop

In questo post vorrei proporvi del codice per poter convertire un file .doc in un file .rtf oppure .pdf utilizzando le API di interoperabilità di Office.Creeremo una classe, DocConverter, che esporrà le due funzionalità sopra citate.Cominciamo con il prevedere un attributo privato della classe che rappresenterà l’applicazione Word che utilizzeremo per la conversione. Creeremo l’istanza dell’attributo privato all’interno del costruttore della classe:PublicSubNew()
IfNot CreateWordApp() Then
ThrowNew ApplicationException("Assembly di interoperabilità con Office non trovato!")
EndIf
EndSub
Private _wordApp As Word.ApplicationClass
ProtectedFunction CreateWordApp() AsBoolean
Dim retval = True
Try
_wordApp = New Word.ApplicationClass()
_wordApp.Visible = False
Catch ex As System.Exception
_wordApp = Nothing
retval = False
EndTry
Return retval
EndFunction

La conversione del file doc sarà effettuata aprendo il file stesso ed eseguendo un’operazione di SaveAs:

Pr…

Cambiare la lingua di Visual Studio 2008

Oggi ho avuto qualche problema installando Windows Mobile 6 Professional SDK Refresh e Windows Mobile 6 Standard SDK Refresh.Scaricati i file di installazione e installati, ho provato a creare un progetto di tipo Windows Mobile 6.0 e mi sono beccato questo errore:Dopo qualche smanettamento abbiamo scoperto (e ringrazio il mitico Matteo per l’aiuto) che il mio Visual Studio 2008, pur essendo in Inglese (prova ne era il fatto che gli hotfix e la SP installata erano nella lingua di Albione) aveva come lingua impostata quella del sistema operativo (italiano).Ovviamente, non avrebbe mai potuto trovare la cartella 1040 (italiano) visto che l’installazione dell’SDK aveva supposto che la lingua del Visual Studio fosse Inglese (1033).La soluzione del problema è duplice:1) Duplicate la cartella 1033 presente nel percorso evidenziato dall’errore e la rinominate 10402) cambiate la lingua di Visual Studio.Per questa ultima eventualità basta andare nel menù Strumenti/Opzioni:e cambiare il linguaggi…

Tascam DR-05 registratore digitale per tutti

Diverso tempo fa ho acquistato il registratore digitale Tascam DR-05 e, ora, dopo diversi mesi di utilizzo, posso dire la mia a proposito.

Si tratta di un ottimo registratore digitale con microfono stereo che permette di ottenere registrazioni di ottima qualitaà anche in ambienti non perfetti dal punto di vista acustico.

Interessante la possibilità di utilizzare un cavalletto di piccole dimensioni come HAMA Mini treppiede o Mini Cavalletto Universale per tenere il microfono sollevato dal tavolo in fase di registrazione grazie allàattacco universale per macchina fotografica che il microfono ha nella parte inferiore.

Da segnalare anche il menu’ ben fatto e la possibilita’ di utilizzare una scheda SD esterna per memorizzare i file audio. Anche a livello di consumo batterie non e’ niente male. Consiglio l’uso delle alcaline non ricaricabili.

Il mio utilizzo e’ stato prettamente di registrazione di podcast vocali (no musica) ma le recensioni confermano che se la cava egregiamente con la mu…