Condividi tramite


Esempio di raccolta di inchiostro RealTimeStylus

Questa applicazione illustra la raccolta e il rendering dell'inchiostro quando si usa la classe RealTimeStylus.

Progetto InkCollection

Questo esempio è costituito da una singola soluzione che contiene un progetto, InkCollection. L'applicazione definisce lo spazio dei nomi InkCollection che contiene una singola classe, denominata anche InkCollection. La classe eredita dalla classe Form e implementa l'interfaccia IStylusAsyncPlugin.

namespace InkCollection
{
    public class InkCollection : Form, IStylusAsyncPlugin
    {
        //...
      

La classe InkCollection definisce un set di costanti private utilizzate per specificare vari spessori di inchiostro. La classe dichiara anche istanze private della classe RealTimeStylus, myRealTimeStylus, la classe DynamicRenderer, myDynamicRenderere il renderer classe myRenderer. Il DynamicRenderer esegue il rendering del Stroke attualmente raccolto. L'oggetto Renderer, myRenderer, esegue il rendering degli oggetti Stroke già raccolti.

private const float ThinInkWidth = 10;
private const float MediumInkWidth = 100;
private const float ThickInkWidth = 200;

private RealTimeStylus myRealTimeStylus;

private DynamicRenderer myDynamicRenderer;
private Renderer myRenderer;

La classe dichiara inoltre un oggetto hashtable, myPackets, utilizzato per archiviare i dati di pacchetto raccolti da uno o più oggetti Cursor. I valori di StylusID vengono usati come chiave di tabella hash per identificare in modo univoco i dati del pacchetto raccolti per un determinato oggetto Cursor.

Un'istanza privata dell'oggetto Ink , myInk, archivia gli oggetti Stroke raccolti da myRealTimeStylus.

private Hashtable myPackets;
        
private Ink myInk;

Evento di caricamento del modulo

Nell'gestore eventi Load per il form myDynamicRenderer viene creata un'istanza utilizzando il DynamicRenderer che accetta un controllo come argomento e myRenderer viene costruito con un costruttore senza argomenti.

private void InkCollection_Load(object sender, System.EventArgs e)
{
    myDynamicRenderer = new DynamicRenderer(this);
    myRenderer = new Renderer();
    // ...

Prestare attenzione al commento che segue la creazione delle istanze dei renderer, perché myDynamicRenderer usa i valori predefiniti per DrawingAttributes durante il rendering dell'inchiostro. Si tratta di un comportamento standard. Tuttavia, se si desidera dare all'inchiostro reso da myDynamicRenderer un aspetto diverso da quello reso da myRenderer, è possibile modificare la proprietà DrawingAttributes su myDynamicRenderer. A tale scopo, rimuovere il commento dalle righe seguenti prima di compilare ed eseguire l'applicazione.

    // myDynamicRenderer.DrawingAttributes.PenTip = PenTip.Rectangle;
    // myDynamicRenderer.DrawingAttributes.Height = (.5F)*MediumInkWidth;
    // myDynamicRenderer.DrawingAttributes.Transparency = 128;

Successivamente, l'applicazione crea l'oggetto RealTimeStylus usato per ricevere notifiche di stilo e aggiunge l'oggetto DynamicRenderer alla coda di notifica del plug-in sincrono. In particolare, myRealTimeStylus aggiunge myDynamicRenderer alla proprietà SyncPluginCollection.

    myRealTimeStylus = new RealTimeStylus(this, true);

    myRealTimeStylus.SyncPluginCollection.Add(myDynamicRenderer);

Il modulo viene quindi aggiunto alla coda asincrona di notifica del plug-in. In particolare, InkCollection viene aggiunto alla proprietà AsyncPluginCollection. Infine, myRealTimeStylus e myDynamicRenderer sono abilitati e myPackets e myInk sono istanziati.

    myRealTimeStylus.AsyncPluginCollection.Add(this);

    myRealTimeStylus.Enabled = true;
    myDynamicRenderer.Enabled = true;  
      
    myPackets = new Hashtable();
    myInk = new Ink();
}

Oltre ad associare i gestori di menu per modificare il colore e le dimensioni dell'inchiostro, è necessario un ulteriore blocco di codice breve prima di implementare l'interfaccia. L'esempio deve gestire l'evento Paint del form. Nel gestore eventi, l'applicazione deve aggiornare myDynamicRenderer perché è possibile che un oggetto Stroke venga raccolto quando si verifica l'evento Paint. In tal caso, la parte dell'oggetto Stroke già raccolta deve essere ridisegnata. Il renderer statico viene utilizzato per disegnare nuovamente oggetti Stroke già raccolti. Questi tratti si trovano nell'oggetto inchiostro perché vengono posizionati lì quando vengono disegnati, come illustrato nella sezione successiva.

private void InkCollection_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
    myDynamicRenderer.Refresh();

    myRenderer.Draw(e.Graphics, myInk.Strokes);
} 

Implementazione dell'interfaccia IStylusAsyncPlugin

L'applicazione di esempio definisce i tipi di notifiche che ha interesse a ricevere nell'implementazione della proprietà DataInterest. La proprietà DataInterest definisce quindi le notifiche che l'oggetto RealTimeStylus inoltra al modulo. Per questo esempio, la proprietà DataInterest definisce l'interesse per le notifiche StylusDown, Packets, StylusUp, e Error tramite l'enumerazione DataInterestMask.

public DataInterestMask DataInterest
{
    get
    {
        return DataInterestMask.StylusDown |
               DataInterestMask.Packets |
               DataInterestMask.StylusUp |
               DataInterestMask.Error;
    }
}

La notifica StylusDown si verifica quando la penna tocca la superficie del digitalizzatore. In questo caso, l'esempio alloca una matrice usata per archiviare i dati del pacchetto per l'oggetto dello stilo. Il StylusDownData dal metodo StylusDown viene aggiunto all'array e l'array viene inserito nella tabella hash utilizzando la proprietà Id dell'oggetto Stylus come chiave.

public void StylusDown(RealTimeStylus sender, StylusDownData data)
{
    ArrayList collectedPackets = new ArrayList();

    collectedPackets.AddRange(data.GetData());

    myPackets.Add(data.Stylus.Id, collectedPackets);
}

La notifica pacchetti si verifica quando la penna si muove sulla superficie del digitalizzatore. In questo caso, l'applicazione aggiunge nuovi StylusDownData nell'array di pacchetti per l'oggetto Stylus . A tale scopo, viene usata la proprietà id dell'oggetto Stylus come chiave per recuperare la matrice di pacchetti per lo stilo dalla tabella hash. I nuovi dati del pacchetto vengono quindi inseriti nella matrice recuperata.

public void Packets(RealTimeStylus sender, PacketsData data)
{
    ((ArrayList)(myPackets[data.Stylus.Id])).AddRange(data.GetData());
}

La notifica StylusUp si verifica quando la penna lascia la superficie del digitalizzatore. Quando si verifica questa notifica, l'esempio recupera dalla tabella hash l'array di pacchetti relativo a questo oggetto Stylus, rimuovendolo poiché non è più necessario, aggiunge i nuovi dati del pacchetto e utilizza l'array di dati del pacchetto per creare un nuovo oggetto Stroke, stroke.

public void StylusUp(RealTimeStylus sender, StylusUpData data)
{
    ArrayList collectedPackets = (ArrayList)myPackets[data.Stylus.Id];
    myPackets.Remove(data.Stylus.Id);

    collectedPackets.AddRange(data.GetData());

    int[] packets = (int[])(collectedPackets.ToArray(typeof(int)));
    TabletPropertyDescriptionCollection tabletProperties =
        myRealTimeStylus.GetTabletPropertyDescriptionCollection(data.Stylus.TabletContextId);

    Stroke stroke = myInk.CreateStroke(packets, tabletProperties);
    if (stroke != null) 
    {
         stroke.DrawingAttributes.Color = myDynamicRenderer.DrawingAttributes.Color;
         stroke.DrawingAttributes.Width = myDynamicRenderer.DrawingAttributes.Width;
    } 
}

Per un esempio che mostra un uso più affidabile della classeRealTimeStylus, incluso l'uso della creazione di plug-in personalizzati, vedere Esempio di plug-in RealTimeStylus.

Microsoft.Ink.Renderer

Microsoft.StylusInput.DynamicRenderer

Microsoft.StylusInput.RealTimeStylus

Microsoft.StylusInput.IStylusAsyncPlugin

accesso e modifica dell'input dello stilo