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 for Dummies: Gli Eventi

Vorrei iniziare con questo post una serie dedicata ad aspetti di VB.NET di base che possono essere utile a coloro che si avvicinano al mondo .NET e che, in genere, non vengono trattati a livello base. La serie di post non ha la pretesa di essere assolutamente esaustivi sugli argomenti che tratterò In questo primo post parleremo degli eventi. Cosa sono e a cosa servono Un evento è la “notifica” dell’accadimento di qualcosa. Quando, ad esempio, premiamo un bottone della finestra di un’applicazione, dietro le quinte, il bottone stesso “notifica” al mondo circostante che qualcuno, in quell’istante, lo ha premuto. Sta, poi, al mondo circostante preoccuparsi di “intercettare” l’evento stesso per gestirlo (tramite un gestore di evento). Attenzione a non confondere la pressione del tasto con la “notifica” della pressione del tasto: l’evento è la “notifica” dell’accadimento, non l’accadimento stesso. Ma a cosa serve tutto ciò? Utilizzare gli eventi è un modo per disaccoppiare

VB.NET: SplashScreen con effetto fade-in

In questo post vorrei proporvi un modo per realizzare una splash screen per le nostre applicazioni Windows Form che appare progressivamente con un effetto fade. Supponiamo di avere il nostro progetto VB.NET in una soluzione Visual Studio 2008 in cui abbiamo il sorgente della nostra applicazione Windows Form. Inseriamo una splash screen utilizzando il menù Progetto->Aggiungi Nuovo Elemento e selezionando il tipo di elemento “Schermata Iniziale” A questo punto Visual Studio creerà, automaticamente, la schermata iniziale che possiamo personalizzare graficamente come vogliamo. Per poter fare in modo che questa finestra appaia nel momento in cui avviamo l’applicazione, è necessario aprire le proprietà del progetto e impostare la maschera di avvio: In questo modo, all’avvio dell’applicazione, la schermata appare immediatamente e scompare un attimo prima della visualizzazione della finestra dell’applicazione. Possiamo far apparire la schermata iniziale con un ef

Alla scoperta del Kinect: presentazioni e convenevoli

Oggi è arrivato un Kinect nuovo nuovo su cui cominciare a fare sperimentazione ed ho, quindi, deciso di condividere tutto ciò che scopro, le cavolate che faccio e i segreti che scopro con chi mi segue. I post che cercherò di scrivere con frequenza sono post di un neofita che si avvicina all’”Aggeggio” e che quindi sono diretti a chi nulla dell’argomento. Gli esperti troveranno noiosi e banali questi post, ma non si può aver tutto dalla vita. Per cominciare, scartato l’”Aggeggio” ho cominciato a preparare l’ambiente di sviluppo: 1) Visual Studio 2010 Ultimate (che uso normalmente ma che non è necessario in quanto si può sviluppare tranquillamente con la express edition); 2) Kinect SDK, scaricabile all’indirizzo http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/download.aspx 3) DirectX Software Development Kit scaricabile all’indirizzo http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=6812 A questo punto vi basta connettere il Kinect al