Il presente articolo è stato tradotto automaticamente.

Nuove frontiere per l'interfaccia utente

Eventi di manipolazione multitocco in WPF

Charles Petzold

Scaricare il codice di esempio

All'interno di negli ultimi anni multi-touch è avanzato da un prop futuristic Pellicola sci-fi a un'interfaccia utente principale. Visualizza Multi-Touch è ora standard sui nuovi modelli di computer gli Smartphone e Tablet PC. Multi-Touch inoltre è probabile che diventano molto diffusa nei computer in spazi pubblici, ad esempio chioschi multimediali o il computer tabella proposto prima volta dall'area di Microsoft.

Solo reale è uncertainly la popolarità di multi-touch sul computer desktop convenzionali. Forse impediment massimo è stanchezza noto come “ gorilla braccio ” associato lo spostamento verticale schermate dita per lunghi periodi di tempo. Spero personale è che la potenza di multi-touch verrà effettivamente provoke una riprogettazione della visualizzazione del desktop. È possibile concepire un PC con una visualizzazione simile alla configurazione di una tabella di bozza e forse quasi le stesse dimensioni.

Ma il futuro (forse). Per il momento, gli sviluppatori hanno nuove API al master. Il supporto per multi-touch in Windows 7 ha filtrato verso il Low e liquidate in varie aree di Microsoft .NET Framework con interfacce alta e Low.

Ordinamento di supporto Multi-Touch

Se si considera la complessità dell'espressione è possibile tramite l'utilizzo di più dita su uno schermo, è possibile apprezzare forse perché nessuno sembra conoscere abbastanza ancora l'interfaccia di programmazione “ corretta ” per multi-touch. L'operazione richiederà alcuni minuti. Nel frattempo, esistono diverse opzioni.

Windows Presentation Foundation (WPF) 4.0 ha due interfacce multi-touch disponibile per i programmi in esecuzione in Windows 7. Per utilizzi specifici di multi-touch, i programmatori desideri esplorare l'interfaccia di Low livello composto da vari eventi indirizzati definiti da UIElement denominato TouchDown, TouchMove, Ritocco, TouchEnter, TouchLeave, con versioni di anteprima dello spostamento verso il Low e gli eventi. Ovviamente questi vengono modellati dopo gli eventi del mouse, con la differenza che è necessaria tenere traccia di più dita sullo schermo una proprietà ID integer. Area di Microsoft si basa su WPF 3.5, ma supporta un'interfaccia di contatto a Low livello più ampia che distingue i tipi e le forme di input tocco.

Il soggetto di questa colonna è il supporto multi-touch ad alto livello in WPF 4.0, costituito da un insieme di eventi i cui nomi iniziano con la parola modifica. Questi eventi di modifica eseguono numerosi processi multi-touch fondamentale:

  • l'interazione di due dita in una singola azione di consolidamento
  • risoluzione lo spostamento di uno o due dita nelle trasformazioni
  • implementazione a inerzia quando le dita dalla schermata

Nella documentazione di Silverlight 4 è elencato un sottoinsieme degli eventi di modifica, ma un po' ingannevole. Gli eventi non sono ancora supportati da Silverlight in sé, ma sono supportate nelle applicazioni Silverlight scritte per Windows telefono 7. Di Figura 1 sono elencati gli eventi di modifica.

Figura 1 di eventi di modifica in Windows Presentation Foundation 4.0

Event Supportato dal telefono Windows 7?
ManipulationStarting No
ManipulationStarted Sì
ManipulationDelta Sì
ManipulationInertiaStarted No
ManipulationBoundaryFeedback No
ManipulationCompleted Sì

 

Applicazioni basate su Web di Silverlight 4 continueranno a utilizzare l'evento Touch.FrameReported discusso nell'articolo “ Finger Style: Esplorazione Multi-Touch Support in Silverlight ” nel numero di marzo 2010 di MSDN Magazine.

Insieme agli eventi modifica delle stesse, la classe UIElement in WPF supporta metodi sottoponibili a override, ad esempio su ­ ManipulationStarting corrispondente per gli eventi di modifica. In Silverlight per Windows telefono 7 vengono definiti i metodi sottoponibili a override dalla classe Control.

Un esempio di Multi-Touch

L'applicazione multi-touch archetipo è probabilmente un visualizzatore di fotografia che consente di trasferire le foto su una superficie, renderli più grandi o più piccoli con due dita e ruotarli. Queste operazioni vengono talvolta definite come pan, zoom e ruotare e corrispondono alle trasformazioni grafiche standard di traduzione, ridimensionamento e rotazione.

Ovviamente un programma per la visualizzazione di una fotografia deve gestire la raccolta di foto, consentire nuove foto da aggiungere e foto da rimuovere ed è sempre utile visualizzare le foto in una cornice grafica poco, ma ho intenzione di ignorare tutto questo e concentrarsi solo sull'interazione multi-touch. Ero sorpresa facilità tutto diventa con gli eventi di modifica e ritengo che sarà anche.

Tutto il codice sorgente per questo articolo è un'unica soluzione scaricabile denominata WpfManipulationSamples. Il primo progetto è SimpleManipulationDemo e viene visualizzato il file MainWindow.xaml in di Figura 2.

Figura 2 del file XAML per SimpleManipulationDemo

 

<Window x:Class="SimpleManipulationDemo.MainWindow"
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  Title="Simple Manipulation Demo">

  <Window.Resources>
    <Style TargetType="Image">
      <Setter Property="Stretch" Value="None" />
      <Setter Property="HorizontalAlignment" Value="Left" />
      <Setter Property="VerticalAlignment" Value="Top" />
    </Style>
  </Window.Resources>

  <Grid>
    <Image Source="Images/112-1283_IMG.JPG"  
      IsManipulationEnabled="True"
      RenderTransform="0.5 0 0 0.5 100 100" />

    <Image Source="Images/139-3926_IMG.JPG"
      IsManipulationEnabled="True"
      RenderTransform="0.5 0 0 0.5 200 200" />
        
    <Image Source="Images/IMG_0972.JPG"
      IsManipulationEnabled="True"
      RenderTransform="0.5 0 0 0.5 300 300" />
        
    <Image Source="Images/IMG_4675.JPG"
      IsManipulationEnabled="True"
      RenderTransform="0.5 0 0 0.5 400 400" />
  </Grid>
  </Window>

Notare innanzitutto l'impostazione su tutti e tre gli elementi immagine:

 

IsManipulationEnabled="True"

Questa proprietà è impostata su false per impostazione predefinita. È necessario impostarla su true per qualsiasi elemento in cui si desidera ottenere input multi-touch e generare eventi di modifica.

Gli eventi di modifica sono eventi indirizzati di WPF, vale a dire che gli eventi propagati nella struttura visiva di. In questo programma, né la griglia MainWindow dispone della proprietà IsManipulationEnabled impostata su true, ma può comunque associare gestori per gli eventi di modifica per gli elementi sulla griglia e MainWindow o eseguire l'override dei metodi della classe MainWindow OnManipulation.

Si noti inoltre che ciascun elemento Image è proprio rendering ­ trasformazione impostata su una stringa di numero sei:

RenderTransform="0.5 0 0 0.5 100 100"

Si tratta di un collegamento che imposta la proprietà RenderTransform su un oggetto MatrixTransform inizializzato. In questo caso specifico, viene inizializzato l'oggetto matrice impostata la MatrixTransform eseguire una scala pari a 0,5 (rendendo le foto della metà le dimensioni effettive) e una traslazione di 100 unità verso destra e verso il basso. Il file code-behind per la finestra accede e modifica questo MatrixTransform.

Il file MainWindow.xaml.cs completo è illustrato in di Figura 3 ed esegue l'override solo due metodi OnManipulationStarting e OnManipulationDelta. Questi metodi di elaborare manipolazioni generate dagli elementi Image.

Figura 3 del file code-behind per SimpleManipulationDemo

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace SimpleManipulationDemo {
  public partial class MainWindow : Window {
    public MainWindow() {
      InitializeComponent();
    }

    protected override void OnManipulationStarting(
      ManipulationStartingEventArgs args) {

      args.ManipulationContainer = this;

      // Adjust Z-order
      FrameworkElement element = 
        args.Source as FrameworkElement;
      Panel pnl = element.Parent as Panel;

      for (int i = 0; i < pnl.Children.Count; i++)
        Panel.SetZIndex(pnl.Children[i],
          pnl.Children[i] == 
          element ? pnl.Children.Count : i);

      args.Handled = true;
      base.OnManipulationStarting(args);
    }

    protected override void OnManipulationDelta(
      ManipulationDeltaEventArgs args) {

      UIElement element = args.Source as UIElement;
      MatrixTransform xform = 
        element.RenderTransform as MatrixTransform;
      Matrix matrix = xform.Matrix;
      ManipulationDelta delta = args.DeltaManipulation;
      Point center = args.ManipulationOrigin;

      matrix.ScaleAt(
        delta.Scale.X, delta.Scale.Y, center.X, center.Y);
      matrix.RotateAt(
        delta.Rotation, center.X, center.Y);
      matrix.Translate(
        delta.Translation.X, delta.Translation.Y);
      xform.Matrix = matrix;

      args.Handled = true;
      base.OnManipulationDelta(args);
    }
  }
  }

Nozioni fondamentali di manipolazione

Una modifica è definita come una o più dita tocca un particolare elemento. Una manipolazione completa inizia con l'evento iniziale di manipolazione ­ (seguita subito seguito da ManipulationStarted) e termina con ManipulationCompleted. Potrebbero esistere tra, molti eventi ManipulationDelta.

Tutti gli eventi di modifica è accompagnato da una serie di argomenti dell'evento in una classe denominata dopo l'evento con EventArgs aggiunto, ad esempio ManipulationStartingEventArgs e ManipulationDeltaEventArgs. Tali classi derivano da InputEventArgs familiare, che a sua volta deriva da RoutedEvent ­ Args. Le classi includono proprietà Source e OriginalSource che indica l'origine dell'evento.

Nel programma SimpleManipulationDemo Source e originale ­ Source verrà sia impostati per l'elemento Image genera gli eventi di modifica. Solo un elemento con la IsManipulation ­ proprietà Enabled è impostata su true sarà visualizzati come proprietà Source e OriginalSource in questi eventi di modifica.

Ciascuna delle classi di argomenti di eventi associate agli eventi di modifica include inoltre una proprietà denominata ­ manipolazione Container. È l'elemento in cui è in corso la manipolazione multi-touch. Tutte le coordinate degli eventi di modifica sono relativamente a questo contenitore.

Per impostazione predefinita, la proprietà ManipulationContainer è impostata per la proprietà Source e OriginalSource stesso elemento, l'elemento modificato, ma è probabile che non si desidera. In generale, non si desidera che il contenitore di manipolazione dello stesso elemento modificato poiché le interazioni difficile ottenere dinamicamente lo spostamento, ridimensionamento e rotazione dell'elemento stesso che riporta le informazioni di contatto. Si desidera invece il contenitore di manipolazione da un elemento padre dell'elemento manipolabili o forse un elemento ulteriormente la struttura visiva.

Nella maggior parte degli eventi di modifica, la proprietà ManipulationContainer è di sola lettura. L'eccezione è l'evento di modifica primo che riceve un elemento. In ManipulationStarting hai l'opportunità di modificare ManipulationContainer in qualcosa di più appropriato. Nel progetto SimpleManipulationDemo questo processo è una singola riga di codice:

args.ManipulationContainer = this;

In tutti gli eventi successivi ManipulationContainer sarà quindi l'elemento MainWindow anziché l'elemento Image e saranno tutte le coordinate rispetto a tale finestra. Funziona correttamente perché il pannello Grid contenente gli elementi dell'immagine è allineato anche nella finestra.

Il resto della OnManipulationStarting metodo dedicato a portare in primo piano l'elemento Image toccato reimpostando il Panel.ZIndex collegate le proprietà di tutti gli elementi dell'immagine della griglia. Si tratta di un modo semplice per gestire ZIndex, ma probabilmente non è la migliore poiché crea modifiche improvvise.

ManipulationDelta e DeltaManipulation

Il solo altri eventi gestiti da SimpleManpulationDemo sono ManipulationDelta. La classe ManipulationDeltaEventArgs definisce due proprietà di tipo ManipulationDelta. (Sì, l'evento e la classe hanno lo stesso nome.) Queste proprietà sono DeltaManipulation e CumulativeManipulation. Come suggeriscono i nomi, DeltaManipulation riflette la modifica che si è verificato dopo l'ultimo evento ManipulationDelta e CumulativeManipulation è la manipolazione completa inizia con l'evento ManipulationStarting.

ManipulationDelta ha quattro proprietà:

  • Conversione di tipo vettoriale
  • Scala di tipo vettoriale
  • Espansione di tipo vettoriale
  • Rotazione di tipo double

La struttura Vector definisce due proprietà denominata X e Y di tipo double. Una delle differenze più importanti con il supporto di modifica in Silverlight per Windows telefono 7 è l'assenza di proprietà espansione e rotazione.

La proprietà Translation indica il movimento (o una pan) nelle direzioni orizzontale e verticale. Un dito su un elemento singolo può generare modifiche in traduzione ma traduzione può anche essere parte di altre modifiche.

La proprietà Scale ed espansione indicare una modifica nelle dimensioni (zoom) richiede sempre due dita. Scala è moltiplicazione ed espansione è additiva. Utilizzare scala per l'impostazione di una trasformazione di scala ed espansione per aumentare o diminuire le proprietà Width e Height di un elemento da unità indipendenti dalla periferica.

In WPF 4.0, i valori X e Y del vettore scala sono sempre gli stessi. Gli eventi di modifica non forniscono informazioni sufficienti per ridimensionare un elemento anisotropically (vale a dire in modo diverso nelle direzioni orizzontale e verticale).

Per impostazione predefinita, rotazione richiede inoltre due dita, sebbene si vedrà in seguito come attivare il dito una rotazione. In qualsiasi caso ManipulationDelta particolare, tutte e quattro le proprietà possono essere impostate. Una coppia di dita potrebbe essere ingrandimento di un elemento e al tempo stesso rotazione e spostarlo in un'altra posizione.

Scaling e rotazione sono sempre rispetto a un punto centrale specifico. Quest'area è inoltre disponibile in ManipulationDeltaEvent ­ Args nella proprietà denominata ManipulationOrigin di tipo Point. Questa origine è relativo a ManipulationContainer impostata nell'evento ManipulationStarting.

Il processo nell'evento ManipulationDelta consiste nel modificare il rendering ­ proprietà di trasformazione dell'oggetto gestibili in base ai valori delta nel seguente ordine: scala in primo luogo, quindi rotazione e infine traduzione. (In realtà, poiché i fattori di scala orizzontali e verticali sono identici, è possibile cambiare l'ordine delle trasformazioni ridimensionamento e rotazione e comunque ottenere lo stesso risultato.)

Il metodo OnManipulationDelta in di Figura 3 illustra un approccio standard. La matrice viene ottenuto dal MatrixTransform impostato sull'elemento Image gestibili. Viene modificato attraverso chiamate a ScaleAt RotateAt (sia relativo alla ManipulationOrigin) e traslazione. Matrice è una struttura anziché una classe, è necessario terminare sostituendo il vecchio valore di MatrixTransform con uno nuovo.

È possibile variare leggermente il codice. Come illustrato, ridimensiona intorno a un centro di questa istruzione:

 

matrix.ScaleAt(delta.Scale.X, delta.Scale.Y, center.X, center.Y);

Equivale alla conversione in negativo del punto centrale, scalabilità e quindi convertendo il backup:

 

matrix.Translate(-center.X, -center.Y); 
matrix.Scale(delta.Scale.X, delta.Scale.Y); 
matrix.Translate(center.X, center.Y);

Metodo RotateAt analogamente può essere sostituito con questo:

matrix.Translate(-center.X, -center.Y); 
matrix.Rotate(delta.Rotation);
matrix.Translate(center.X, center.Y);

Le due chiamate Traduci adiacenti ora Annulla reciprocamente, pertanto la composizione:

matrix.Translate(-center.X, -center.Y); 
matrix.Scale(delta.Scale.X, delta.Scale.Y);
matrix.Rotate(delta.Rotation); 
matrix.Translate(center.X, center.Y);

È probabile che un po' più efficace.

Figura 4 viene illustrato il programma SimpleManipulationDemo in azione.

Figura 4 Il programma SimpleManipulationDemo

Abilitazione del contenitore?

Una delle caratteristiche del programma SimpleManpulationDemo interessante è che è possibile contemporaneamente modificare due elementi di immagine o anche più se si dispone del supporto hardware e un numero sufficiente di dita. Ogni elemento Image genera il proprio evento ManipulationStarting e una propria serie di eventi di modifica ­ delta. Il codice in modo efficace consente di distinguere tra più elementi di immagine per la proprietà Source di argomenti dell'evento.

Per questo motivo, è importante non impostare eventuali informazioni sullo stato in campi che ne conseguono che può essere modificato solo un elemento alla volta.

Poiché ogni elemento Image dispone del proprio set di proprietà IsManipulationEnabled su true, è possibile la gestione simultanea di più elementi. Ciascuno di essi può generare una serie univoca di eventi di modifica.

Per raggiungere questi eventi di modifica per la prima volta, si potrebbe provare invece impostando IsManpulationEnabled su true solo per la classe MainWindow o un altro elemento che funge da contenitore. Ciò è possibile, ma è piuttosto clumsier in pratica e non abbastanza come potente. Solo vero vantaggio è che non è necessario impostare la proprietà ManipulationContainer nell'evento ManipulationStarting. La messiness fornita successivamente quando è necessario determinare quale elemento manipolato dall'hit testing sugli elementi figlio utilizzando la proprietà ManipulationOrigin nell'evento ManipulatedStarted.

È necessario archiviare l'elemento modificato come un campo per utilizzare in futuro ManipulationDelta eventi. In questo caso è sicuro archiviare le informazioni sullo stato nei campi perché solo sarà in grado di gestire un elemento nel contenitore alla volta.

La modalità di modifica

Come si è visto, una delle proprietà fondamentali per impostare durante l'evento ManipulationStarting è il ManipulationContainer. Un'altra coppia di proprietà è utili per personalizzare la manipolazione particolare.

È possibile limitare i tipi di modifica che è possibile eseguire l'inizializzazione della proprietà modalità con un membro di ­ Modifica modalità di enumerazione. Ad esempio, se si utilizzava la manipolazione esclusivamente per lo scorrimento orizzontale, è consigliabile limitare gli eventi di conversione solo orizzontale. Il programma ManipulationModesDemo consente di impostare la modalità dinamica visualizzando un elenco di elementi RadioButton Elenca le opzioni, come illustrato in di Figura 5.

Figure 5 The ManipulationModeDemo Display

Figura 5 Il Display ManipulationModeDemo

Naturalmente, il pulsante di opzione è uno dei numerosi controlli in WPF 4.0 rispondono direttamente a contatto.

La rotazione Finger Single

Per impostazione predefinita, è necessario che due dita per ruotare un oggetto. Tuttavia, una foto reale si trova su una scrivania reale, è possibile inserire il dito sull'angolo e ruotarlo in un cerchio. Approssimativamente è in corso la rotazione intorno al centro dell'oggetto.

È possibile farlo con gli eventi di modifica impostando la proprietà pivot di ManipulationStartingEventArgs. Per impostazione predefinita il pivot proprietà è null, si attiva un dito rotazione impostando la proprietà su un oggetto ManipulationPivot. La proprietà fondamentale del
ManipulationPivot è centro, è possibile calcolare il centro dell'elemento da modificare:

 

Point center = new Point(element.ActualWidth / 2, element.ActualHeight / 2);

Ma il punto centrale deve essere relativo al contenitore di manipolazione, che nei programmi ho stato illustrando l'elemento gestisce gli eventi. Tale punto centrale dall'elemento modificato al contenitore di traduzione è semplice:

center = element.TranslatePoint(center, this);

Anche altre poche informazioni deve essere impostata. Se invece si sta specificando un punto centrale, si verifica un problema quando si mette il dito destra al centro dell'elemento: solo un piccolo spostamento causerà l'elemento di selezione intorno ad esempio crazy! Per questo motivo, ManipulationPivot dispone inoltre di una proprietà Radius. Rotazione non si verificherà se il dito all'interno di unità raggio del punto Center. Il programma ManipulationPivotDemo imposta il raggio a mezzo pollice:

args.Pivot = new ManipulationPivot(center, 48);

Ora un dito singolo può eseguire una combinazione di rotazione e traslazione.

Oltre gli elementi di base

Cosa si è visto sono l'utilizzo degli eventi WPF 4.0 manipolazione di base. Naturalmente, esistono alcune variazioni su queste tecniche che mostrerò in futuro colonne, nonché la potenza di manipolazione a inerzia.

Puoi anche dare un'occhiata Superficie Toolkit per Windows Touch , che fornisce controlli tocco ottimizzato per le applicazioni. Il controllo ScatterView in particolare Elimina la necessità di utilizzo degli eventi modifica direttamente per il materiale di base come la modifica di fotografie. Dispone di alcuni effetti elegante e comportamenti verranno assicurarsi che l'applicazione si comporta come altre applicazioni tocco.

Charles Petzold è consulente redattore esperti di MSDN Magazine. Egli è attualmente scrivendo “ Programming Windows telefono 7, ” che verrà pubblicato come un e-book scaricabile gratuitamente nell'autunno del 2010. Una versione di anteprima è disponibile tramite il suo sito Web, charlespetzold.com .

Grazie ai seguenti esperti tecnici per la revisione di questo articolo: Doug Kramer, Robert tassa e Anson Tsao