Esempio di cancellazione dell'input penna
Questa applicazione si basa sull'esempio di esempio di raccolta input penna illustrando l'eliminazione dei tratti penna. L'esempio fornisce all'utente un menu che dispone di quattro modalità da scegliere: abilitata per l'input penna, cancellazione in cusp, cancellazione di intersezioni e tratti di cancellazione.
In modalità penna abilitata, l'oggetto InkCollector raccoglie l'input penna come illustrato nell'esempio di raccolta input penna.
In modalità di cancellazione, i segmenti di tratti penna esistenti che l'utente tocca con il cursore vengono cancellati. Inoltre, i cusps o gli intersezioni possono essere contrassegnati con un cerchio rosso.
Le parti più interessanti di questo esempio si trovano nel InkErase
gestore eventi del OnPaint
modulo e nelle funzioni di cancellazione chiamate dal gestore eventi del OnMouseMove
modulo.
Circling the Cusps and Intersezioni
Il gestore eventi del OnPaint
modulo disegna prima i tratti e, a seconda della modalità applicazione, può trovare e contrassegnare tutti i cusps o intersezioni con un piccolo cerchio rosso. Una cuspide contrassegna il punto in cui un tratto cambia direzione bruscamente. Un'intersezione contrassegna un punto in cui un tratto si interseca con se stesso o un altro tratto.
L'evento Paint si verifica ogni volta che viene ridisegnato un controllo.
Nota
L'esempio forza il modulo a ridisegnarsi ogni volta che un tratto viene cancellato o quando la modalità applicazione viene modificata, usando il metodo Refresh del modulo.
private void InkErase_OnPaint(object sender, PaintEventArgs e)
{
Strokes strokesToPaint = myInkCollector.Ink.Strokes;
myInkCollector.Renderer.Draw(e.Graphics, strokesToPaint);
switch (mode)
{
case ApplicationMode.CuspErase:
PaintCusps(e.Graphics, strokesToPaint);
break;
case ApplicationMode.IntersectErase:
PaintIntersections(e.Graphics, strokesToPaint);
break;
}
}
In PaintCusps
, il codice esegue l'iterazione di ogni cuspide in ogni tratto e disegna un cerchio rosso intorno a esso. La proprietà PolylineCusps del tratto restituisce gli indici dei punti all'interno di un stoke corrispondente a cusps. Si noti anche il metodo InkSpaceToPixel dell'oggetto Renderer, che converte il punto in coordinate pertinenti al metodo DrawEllipse.
private void PaintCusps(Graphics g, Strokes strokesToPaint)
{
foreach (Stroke currentStroke in strokesToPaint)
{
int[] cusps = currentStroke.PolylineCusps;
foreach (int i in cusps)
{
Point pt = currentStroke.GetPoint(i);
// Convert the X, Y position to Window based pixel coordinates
myInkCollector.Renderer.InkSpaceToPixel(g, ref pt);
// Draw a red circle as the cusp position
g.DrawEllipse(Pens.Red, pt.X-3, pt.Y-3, 6, 6);
}
}
}
In PaintIntersections
, il codice esegue l'iterazione di ogni tratto per trovare le sue intersezioni con l'intero set di tratti. Si noti che il metodo FindIntersections del tratto viene passato un insieme Strokes e restituisce una matrice di valori di indice a virgola mobile che rappresentano gli intersezioni. Il codice calcola quindi una coordinata X-Y per ogni intersezione e disegna un cerchio rosso intorno a esso.
private void PaintIntersections(Graphics g, Strokes strokesToPaint)
{
foreach (Stroke currentStroke in strokesToPaint)
{
float[] intersections = currentStroke.FindIntersections(strokesToPaint);
}
}
Gestione di una penna con due estremità
Tre gestori eventi sono definiti per l'oggetto InkCollector per gli eventi CursorDown, NewPackets e Stroke . Ogni gestore eventi controlla la proprietà Inverted dell'oggetto Cursor per verificare quale fine della penna viene usata. Quando la penna viene invertita:
- Il
myInkCollector_CursorDown
metodo rende trasparente il tratto. - Il
myInkCollector_NewPackets
metodo cancella i tratti. - Il
myInkCollector_Stroke
metodo annulla l'evento. Gli eventi NewPackets vengono generati prima dell'evento Stroke .
Rilevamento del cursore
Se l'utente usa una penna o un mouse, vengono generati eventi MouseMove . Il gestore eventi MouseMove controlla prima di tutto se la modalità corrente è una modalità di cancellazione e se viene premuto un pulsante del mouse e ignora l'evento se questi stati non sono presenti. Il gestore eventi converte quindi le coordinate pixel per il cursore in coordinate dello spazio penna usando il metodo PixelToInkSpace dell'oggetto Renderer e chiama uno dei metodi di cancellazione del codice a seconda della modalità di cancellazione corrente.
Elimina tratti
Il EraseStrokes
metodo accetta la posizione del cursore nello spazio penna e genera una raccolta di tratti che si trovano all'interno HitTestRadius
di unità. Il currentStroke
parametro specifica un oggetto Stroke che non deve essere eliminato. L'insieme di tratti viene quindi eliminato dall'agente di raccolta e il modulo viene ridisegnato.
private void EraseStrokes(Point pt, Stroke currentStroke)
{
Strokes strokesHit = myInkCollector.Ink.HitTest(pt, HitTestRadius);
if (null!=currentStroke && strokesHit.Contains(currentStroke))
{
strokesHit.Remove(currentStroke);
}
myInkCollector.Ink.DeleteStrokes(strokesHit);
if (strokesHit.Count > 0)
{
this.Refresh();
}
}
Cancellazione in intersezioni
Il EraseAtIntersections
metodo esegue l'iterazione di ogni tratto che rientra nel raggio di test e genera una matrice di intersezioni tra tale tratto e tutti gli altri tratti della raccolta. Se non vengono trovati intersezioni, l'intero tratto viene eliminato; in caso contrario, il punto più vicino del tratto al punto di test si trova e da questo, le intersezioni su entrambi i lati del punto si trovano, descrivendo il segmento da rimuovere.
Il metodo Split dell'oggetto Stroke viene usato per separare il segmento dal resto del tratto e quindi il segmento viene eliminato, lasciando invariato il resto del tratto. Come in EraseStrokes
, il modulo viene ridisegnato prima che il metodo restituisca.
private void EraseAtIntersections(Point pt)
{
Strokes strokesHit = myInkCollector.Ink.HitTest(pt, HitTestRadius);
foreach (Stroke currentStroke in strokesHit)
{
float[] intersections = currentStroke.FindIntersections(myInkCollector.Ink.Strokes);
...
float findex = currentStroke.NearestPoint(pt);
...
strokeToDelete = currentStroke.Split(intersections[i]);
...
}
...
}
Cancellazione in Cusps
Per ogni tratto che rientra nel raggio di test, il EraseAtCusps
metodo recupera la matrice di cusps dal metodo PolylineCusps dell'oggetto Stroke. Ogni fine del tratto è anche una cuspide, quindi se il tratto ha solo due cusps, l'intero tratto viene eliminato; in caso contrario, il punto più vicino del tratto al punto di test si trova e da questo, le intersezioni su entrambi i lati del punto si trovano, descrivendo il segmento da rimuovere.
Il metodo Split dell'oggetto Stroke viene usato per separare il segmento dal resto del tratto e quindi il segmento viene eliminato, lasciando invariato il resto del tratto. Come in EraseStrokes
, il modulo viene ridisegnato prima che il metodo restituisca.
private void EraseAtCusps(Point pt)
{
...
strokesHit = myInkCollector.Ink.HitTest(pt, HitTestRadius);
foreach (Stroke currentStroke in strokesHit)
{
int[] cusps = currentStroke.PolylineCusps;
...
float findex = currentStroke.NearestPoint(pt);
...
strokeToDelete = currentStroke.Split(cusps[i]);
myInkCollector.Ink.DeleteStroke(strokeToDelete);
...
}
...
}
Chiusura del modulo
Il metodo Dispose del modulo elimina l'oggetto InkCollector , myInkCollector
.