Esempio di plug-in RealTimeStylus
Questa applicazione illustra l'uso della classe RealTimeStylus . Per una panoramica dettagliata delle API StylusInput, inclusa la classe RealTimeStylus , vedere Accesso e modifica dell'input dello stilo. Per informazioni sui plug-in sincroni e asincroni, vedere Plug-in e la classe RealTimeStylus.
Panoramica dell'esempio
I plug-in, gli oggetti che implementano l'interfaccia IStylusSyncPlugin o IStylusAsyncPlugin possono essere aggiunti a un oggetto RealTimeStylus . Questa applicazione di esempio usa diversi tipi di plug-in:
- Plug-in filtro pacchetti: modifica i pacchetti. Il plug-in del filtro pacchetti in questo esempio modifica le informazioni sui pacchetti vincolando tutti i dati dei pacchetti (x,y) all'interno di un'area rettangolare.
- Plug-in renderer dinamico personalizzato: modifica le qualità di rendering dinamico. Il plug-in di rendering dinamico personalizzato in questo esempio modifica la modalità di rendering dell'input penna disegnando un piccolo cerchio attorno a ogni punto (x,y) su un tratto.
- Plug-in renderer dinamico: modifica le qualità di rendering dinamico. Questo esempio illustra l'uso dell'oggetto DynamicRenderer come plug-in per gestire il rendering dinamico dell'input penna.
- Plug-in riconoscimento movimenti: riconosce i movimenti dell'applicazione. In questo esempio viene illustrato l'uso dell'oggetto GestureRecognizer come plug-in per riconoscere i movimenti dell'applicazione (durante l'esecuzione in un sistema con il riconoscimento movimento Microsoft presente).
In questo esempio viene inoltre fornita un'interfaccia utente che consente all'utente di aggiungere, rimuovere e modificare l'ordine di ogni plug-in nella raccolta. La soluzione di esempio contiene due progetti, RealTimeStylusPluginApp e RealTimeStylusPlugins. RealTimeStylusPluginApp contiene l'interfaccia utente per l'esempio. RealTimeStylusPlugins contiene le implementazioni dei plug-in. Il progetto RealTimeStylusPlugins definisce lo spazio dei nomi RealTimeStylusPlugins, che contiene il filtro dei pacchetti e i plug-in del renderer dinamico personalizzati. Questo spazio dei nomi viene fatto riferimento dal progetto RealTimeStylusPluginApp. Il progetto RealTimeStylusPlugins usa gli spazi dei nomi Microsoft.Ink, Microsoft.StylusInput e Microsoft.StylusInput.PluginData .
Per una panoramica degli spazi dei nomi Microsoft.StylusInput e Microsoft.StylusInput.PluginData , vedere Architettura delle API StylusInput.
Plug-in filtro pacchetti
Il plug-in di filtro pacchetti è un plug-in sincrono che illustra la modifica dei pacchetti. In particolare, definisce un rettangolo nel form. Tutti i pacchetti disegnati all'esterno dell'area vengono visualizzati all'interno dell'area. La classe plug-in, PacketFilterPlugin
, esegue la registrazione per la notifica degli eventi di StylusDown
StylusUp
input penna , e Packets
. La classe implementa i metodi StylusDown, StylusUp e Packets definiti nella classe IStylusSyncPlugin .
Il costruttore pubblico per PacketFilterPlugin
richiede una struttura Rectangle . Questo rettangolo definisce l'area rettangolare, in coordinate dello spazio input penna (.01mm = 1 unità HIMETRIC), in cui saranno contenuti i pacchetti. Il rettangolo viene mantenuto in un campo privato, rectangle
.
public class PacketFilterPlugin:IStylusSyncPlugin
{
private System.Drawing.Rectangle rectangle = System.Drawing.Rectangle.Empty;
public PacketFilterPlugin(Rectangle r)
{
rectangle = r;
}
// ...
La PacketFilterPlugin
classe esegue la registrazione per le notifiche degli eventi implementando la funzione di accesso get per la proprietà DataInterest . In questo caso, il plug-in è interessato a rispondere alle StylusDown
notifiche , Packets
, StylusUp
e Error
. L'esempio restituisce questi valori come definito nell'enumerazione DataInterestMask . Il metodo StylusDown viene chiamato quando la punta della penna contatta la superficie del digitalizzatore. Il metodo StylusUp viene chiamato quando la punta della penna lascia la superficie del digitalizzatore. Il metodo Packets viene chiamato quando l'oggetto RealTimeStylus riceve pacchetti. Il metodo Error viene chiamato quando il plug-in corrente o un plug-in precedente genera un'eccezione.
public DataInterestMask DataInterest
{
get
{
return DataInterestMask.StylusDown |
DataInterestMask.Packets |
DataInterestMask.StylusUp |
DataInterestMask.Error;
}
}
//...
La PacketFilterPlugin
classe gestisce la maggior parte di queste notifiche in un metodo helper, ModifyPacketData
. Il ModifyPacketData
metodo ottiene i valori x e y per ogni nuovo pacchetto dalla classe PacketsData . Se uno dei due valori si trova all'esterno del rettangolo, il metodo sostituisce il valore con il punto più vicino che rimane all'interno del rettangolo. Questo è un esempio di come un plug-in può sostituire i dati dei pacchetti ricevuti dal flusso di input penna.
private void ModifyPacketData(StylusDataBase data)
{
for (int i = 0; i < data.Count ; i += data.PacketPropertyCount)
{
// packet data always has x followed by y followed by the rest
int x = data[i];
int y = data[i+1];
// Constrain points to the input rectangle
x = Math.Max(x, rectangle.Left);
x = Math.Min(x, rectangle.Right);
y = Math.Max(y, rectangle.Top);
y = Math.Min(y, rectangle.Bottom);
// If necessary, modify the x,y packet data
if (x != data[i])
{
data[i] = x;
}
if (y != data[i+1])
{
data[i+1] = y;
}
}
}
Plug-in renderer dinamico personalizzato
La CustomDynamicRenderer
classe implementa anche la classe IStylusSyncPlugin per ricevere notifiche di input penna. Gestisce quindi la Packets
notifica per disegnare un piccolo cerchio attorno a ogni nuovo punto di pacchetto.
La classe contiene una variabile Graphics che contiene un riferimento all'oggetto grafico passato al costruttore della classe. Si tratta dell'oggetto grafico usato per il rendering dinamico.
private Graphics myGraphics;
public CustomDynamicRendererPlugin(Graphics g)
{
myGraphics = g;
}
//...
Quando il plug-in del renderer dinamico personalizzato riceve una notifica Pacchetti, estrae i dati (x,y) e disegna un piccolo cerchio verde intorno al punto. Questo è un esempio di rendering personalizzato basato sul flusso di input penna.
public void Packets(RealTimeStylus sender, PacketsData data)
{
for (int i = 0; i < data.Count; i += data.PacketPropertyCount)
{
// Packet data always has x followed by y followed by the rest
Point point = new Point(data[i], data[i+1]);
// Since the packet data is in Ink Space coordinates, we need to convert to Pixels...
point.X = (int)Math.Round((float)point.X * (float)myGraphics.DpiX/2540.0F);
point.Y = (int)Math.Round((float)point.Y * (float)myGraphics.DpiY/2540.0F);
// Draw a circle corresponding to the packet
myGraphics.DrawEllipse(Pens.Green, point.X - 2, point.Y - 2, 4, 4);
}
}
Progetto RealTimeStylusPluginApp
Il progetto RealTimeStylusPluginApp illustra i plug-in descritti in precedenza, nonché i plug-in GestureRecognizer e DynamicRenderer . L'interfaccia utente del progetto è costituita da:
- Modulo contenente un controllo GroupBox utilizzato per definire l'area di immissione dell'input penna.
- Controllo CheckedListBox da elencare e selezionare i plug-in disponibili.
- Coppia di oggetti Button per abilitare la riordinamento dei plug-in.
Il progetto definisce una struttura, PlugInListItem
, per semplificare la gestione dei plug-in usati nel progetto. La PlugInListItem
struttura contiene il plug-in e una descrizione.
La RealTimeStylusPluginApp
classe stessa implementa la classe IStylusAsyncPlugin . Ciò è necessario in modo che la RealTimeStylusPluginApp
classe possa ricevere una notifica quando il plug-in GestureRecognizer aggiunge i dati dei movimenti alla coda di output. L'applicazione esegue la registrazione per la notifica di CustomStylusDataAdded. Quando i dati dei movimenti sono ricevuti, RealTimeStylusPluginApp
inserisce una descrizione sulla barra di stato nella parte inferiore del modulo.
public void CustomStylusDataAdded(RealTimeStylus sender, CustomStylusData data)
{
if (data.CustomDataId == GestureRecognizer.GestureRecognitionDataGuid)
{
GestureRecognitionData grd = data.Data as GestureRecognitionData;
if (grd != null)
{
if (grd.Count > 0)
{
GestureAlternate ga = grd[0];
sbGesture.Text = "Gesture=" + ga.Id + ", Confidence=" + ga.Confidence;
}
}
}
}
Nota
Nell'implementazione CustomStylusDataAdded è interessante identificare i dati dei movimenti personalizzati nella coda di output tramite GUID (usando il campo GestureRecognitionDataGuid ) o per tipo (usando il risultato dell'istruzione as). L'esempio usa entrambe le tecniche di identificazione a scopo dimostrativo. Entrambi gli approcci da soli sono validi.
Nel gestore eventi Load del modulo l'applicazione crea istanze delle PacketFilter
classi e CustomDynamicRenderer
e le aggiunge alla casella di riepilogo. L'applicazione tenta quindi di creare un'istanza della classe GestureRecognizer e, in caso di esito positivo, lo aggiunge alla casella di riepilogo. Questo errore ha esito negativo se il riconoscimento movimento non è presente nel sistema. L'applicazione crea quindi un'istanza di un oggetto DynamicRenderer e la aggiunge alla casella di riepilogo. Infine, l'applicazione abilita ogni plug-in e l'oggetto RealTimeStylus stesso.
Un altro aspetto importante da notare è che nei metodi helper l'oggetto RealTimeStylus viene prima disabilitato prima che i plug-in vengano aggiunti o rimossi e quindi riabilitato dopo il completamento dell'aggiunta o della rimozione.
private void RemoveFromPluginCollection(int index)
{
IStylusSyncPlugin plugin = ((PluginListItem)chklbPlugins.Items[index]).Plugin;
bool rtsEnabled = myRealTimeStylus.Enabled;
myRealTimeStylus.Enabled = false;
myRealTimeStylus.SyncPluginCollection.Remove(plugin);
myRealTimeStylus.Enabled = rtsEnabled;
}
Argomenti correlati