Not
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Med egenskapen DrawingAttributes för en linje kan du ange utseendet på en linje, till exempel dess storlek, färg och form, men det kan finnas tillfällen då du vill anpassa utseendet utöver vad DrawingAttributes tillåter. Du kanske vill anpassa utseendet på pennanteckningar genom att återge utseendet på en luftborste, oljefärg och många andra effekter. Med Windows Presentation Foundation (WPF) kan du anpassa bläckgrafik genom implementering av ett anpassat DynamicRenderer- och Stroke-objekt.
Det här avsnittet innehåller följande underavsnitt:
Arkitektur
Tuschrendering sker två gånger; När en användare skriver på en yta och igen efter att strecket har lagts till på den aktiverade ytan. DynamicRenderer återger pennanteckningen när användaren flyttar tabletpennan på digitaliseraren och Stroke återges när den har lagts till i ett element.
Det finns tre klasser att implementera när du dynamiskt återger pennanteckningar.
DynamicRenderer: Implementera en klass som härleds från DynamicRenderer. Den här klassen är en specialiserad StylusPlugIn som återger linjen när den ritas. Den DynamicRenderer gör renderingen på en separat tråd, så pennytan verkar samla bläck även när användargränssnittstråden blockeras. Mer information om trådningsmodellen finns i The Ink Threading Model. Om du vill anpassa dynamisk återgivning av en linje åsidosätter du metoden OnDraw.
Stroke: Implementera en klass som härleds från Stroke. Den här klassen ansvarar för statisk återgivning av StylusPoint data när de har konverterats till ett Stroke objekt. Åsidosätt DrawCore-metoden för att säkerställa att den statiska återgivningen av strecket är konsekvent med den dynamiska återgivningen.
InkCanvas: Implementera en klass som härleds från InkCanvas. Tilldela den anpassade DynamicRenderer till egenskapen DynamicRenderer. Åsidosätt metoden OnStrokeCollected och lägg till en anpassad linjestil till egenskapen Strokes. Detta säkerställer att bläckets utseende är konsekvent.
Implementera en dynamisk renderare
Även om klassen DynamicRenderer är en standarddel av WPF måste du skapa en anpassad dynamisk renderare som härleds från DynamicRenderer och åsidosätta metoden OnDraw för att kunna utföra mer specialiserad återgivning.
Följande exempel visar en anpassad DynamicRenderer som ritar med bläck i en linjär gradienteffekt.
using System;
using System.Windows.Media;
using System.Windows;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Input;
using System.Windows.Ink;
Imports System.Windows.Media
Imports System.Windows
Imports System.Windows.Input.StylusPlugIns
Imports System.Windows.Input
Imports System.Windows.Ink
// A StylusPlugin that renders ink with a linear gradient brush effect.
class CustomDynamicRenderer : DynamicRenderer
{
[ThreadStatic]
static private Brush brush = null;
[ThreadStatic]
static private Pen pen = null;
private Point prevPoint;
protected override void OnStylusDown(RawStylusInput rawStylusInput)
{
// Allocate memory to store the previous point to draw from.
prevPoint = new Point(double.NegativeInfinity, double.NegativeInfinity);
base.OnStylusDown(rawStylusInput);
}
protected override void OnDraw(DrawingContext drawingContext,
StylusPointCollection stylusPoints,
Geometry geometry, Brush fillBrush)
{
// Create a new Brush, if necessary.
brush ??= new LinearGradientBrush(Colors.Red, Colors.Blue, 20d);
// Create a new Pen, if necessary.
pen ??= new Pen(brush, 2d);
// Draw linear gradient ellipses between
// all the StylusPoints that have come in.
for (int i = 0; i < stylusPoints.Count; i++)
{
Point pt = (Point)stylusPoints[i];
Vector v = Point.Subtract(prevPoint, pt);
// Only draw if we are at least 4 units away
// from the end of the last ellipse. Otherwise,
// we're just redrawing and wasting cycles.
if (v.Length > 4)
{
// Set the thickness of the stroke based
// on how hard the user pressed.
double radius = stylusPoints[i].PressureFactor * 10d;
drawingContext.DrawEllipse(brush, pen, pt, radius, radius);
prevPoint = pt;
}
}
}
}
' A StylusPlugin that renders ink with a linear gradient brush effect.
Class CustomDynamicRenderer
Inherits DynamicRenderer
<ThreadStatic()> _
Private Shared brush As Brush = Nothing
<ThreadStatic()> _
Private Shared pen As Pen = Nothing
Private prevPoint As Point
Protected Overrides Sub OnStylusDown(ByVal rawStylusInput As RawStylusInput)
' Allocate memory to store the previous point to draw from.
prevPoint = New Point(Double.NegativeInfinity, Double.NegativeInfinity)
MyBase.OnStylusDown(rawStylusInput)
End Sub
Protected Overrides Sub OnDraw(ByVal drawingContext As DrawingContext, _
ByVal stylusPoints As StylusPointCollection, _
ByVal geometry As Geometry, _
ByVal fillBrush As Brush)
' Create a new Brush, if necessary.
If brush Is Nothing Then
brush = New LinearGradientBrush(Colors.Red, Colors.Blue, 20.0)
End If
' Create a new Pen, if necessary.
If pen Is Nothing Then
pen = New Pen(brush, 2.0)
End If
' Draw linear gradient ellipses between
' all the StylusPoints that have come in.
Dim i As Integer
For i = 0 To stylusPoints.Count - 1
Dim pt As Point = CType(stylusPoints(i), Point)
Dim v As Vector = Point.Subtract(prevPoint, pt)
' Only draw if we are at least 4 units away
' from the end of the last ellipse. Otherwise,
' we're just redrawing and wasting cycles.
If v.Length > 4 Then
' Set the thickness of the stroke based
' on how hard the user pressed.
Dim radius As Double = stylusPoints(i).PressureFactor * 10.0
drawingContext.DrawEllipse(brush, pen, pt, radius, radius)
prevPoint = pt
End If
Next i
End Sub
End Class
Implementera anpassade streck
Implementera en klass som härleds från Stroke. Den här klassen ansvarar för att återge StylusPoint data när de har konverterats till ett Stroke objekt. Åsidosätt klassen DrawCore för att utföra den faktiska ritningen.
Klassen Stroke kan också lagra anpassade data med hjälp av metoden AddPropertyData. Dessa data lagras med linjedata när de sparas.
Klassen Stroke kan också utföra träfftestning. Du kan också implementera din egen algoritm för träfftestning genom att åsidosätta metoden HitTest i den aktuella klassen.
Följande C#-kod visar en anpassad Stroke-klass som återger StylusPoint data som en 3D-linje.
using System;
using System.Windows.Media;
using System.Windows;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Input;
using System.Windows.Ink;
Imports System.Windows.Media
Imports System.Windows
Imports System.Windows.Input.StylusPlugIns
Imports System.Windows.Input
Imports System.Windows.Ink
// A class for rendering custom strokes
class CustomStroke : Stroke
{
Brush brush;
Pen pen;
public CustomStroke(StylusPointCollection stylusPoints)
: base(stylusPoints)
{
// Create the Brush and Pen used for drawing.
brush = new LinearGradientBrush(Colors.Red, Colors.Blue, 20d);
pen = new Pen(brush, 2d);
}
protected override void DrawCore(DrawingContext drawingContext,
DrawingAttributes drawingAttributes)
{
// Allocate memory to store the previous point to draw from.
Point prevPoint = new Point(double.NegativeInfinity,
double.NegativeInfinity);
// Draw linear gradient ellipses between
// all the StylusPoints in the Stroke.
for (int i = 0; i < this.StylusPoints.Count; i++)
{
Point pt = (Point)this.StylusPoints[i];
Vector v = Point.Subtract(prevPoint, pt);
// Only draw if we are at least 4 units away
// from the end of the last ellipse. Otherwise,
// we're just redrawing and wasting cycles.
if (v.Length > 4)
{
// Set the thickness of the stroke
// based on how hard the user pressed.
double radius = this.StylusPoints[i].PressureFactor * 10d;
drawingContext.DrawEllipse(brush, pen, pt, radius, radius);
prevPoint = pt;
}
}
}
}
' A class for rendering custom strokes
Class CustomStroke
Inherits Stroke
Private brush As Brush
Private pen As Pen
Public Sub New(ByVal stylusPoints As StylusPointCollection)
MyBase.New(stylusPoints)
' Create the Brush and Pen used for drawing.
brush = New LinearGradientBrush(Colors.Red, Colors.Blue, 20.0)
pen = New Pen(brush, 2.0)
End Sub
Protected Overrides Sub DrawCore(ByVal drawingContext As DrawingContext, _
ByVal drawingAttributes As DrawingAttributes)
' Allocate memory to store the previous point to draw from.
Dim prevPoint As New Point(Double.NegativeInfinity, Double.NegativeInfinity)
' Draw linear gradient ellipses between
' all the StylusPoints in the Stroke.
Dim i As Integer
For i = 0 To Me.StylusPoints.Count - 1
Dim pt As Point = CType(Me.StylusPoints(i), Point)
Dim v As Vector = Point.Subtract(prevPoint, pt)
' Only draw if we are at least 4 units away
' from the end of the last ellipse. Otherwise,
' we're just redrawing and wasting cycles.
If v.Length > 4 Then
' Set the thickness of the stroke
' based on how hard the user pressed.
Dim radius As Double = Me.StylusPoints(i).PressureFactor * 10.0
drawingContext.DrawEllipse(brush, pen, pt, radius, radius)
prevPoint = pt
End If
Next i
End Sub
End Class
Implementera en anpassad InkCanvas
Det enklaste sättet att använda dina anpassade DynamicRenderer och penseldrag är att implementera en klass som härleds från InkCanvas och använder dessa klasser. InkCanvas har en DynamicRenderer-egenskap som anger hur linjen återges när användaren ritar den.
Om du vill anpassa återgivningsstreck på en InkCanvas gör du följande:
Skapa en klass som härleds från InkCanvas.
Tilldela din anpassade DynamicRenderer till egenskapen InkCanvas.DynamicRenderer.
Åsidosätt metoden OnStrokeCollected. I den här metoden tar du bort den ursprungliga linje som lades till i InkCanvas. Skapa sedan en anpassad linje, lägg till den i egenskapen Strokes och anropa basklassen med en ny InkCanvasStrokeCollectedEventArgs som innehåller den anpassade linjen.
Följande C#-kod visar en anpassad InkCanvas-klass som använder en anpassad DynamicRenderer och samlar in anpassade streck.
public class CustomRenderingInkCanvas : InkCanvas
{
CustomDynamicRenderer customRenderer = new CustomDynamicRenderer();
public CustomRenderingInkCanvas() : base()
{
// Use the custom dynamic renderer on the
// custom InkCanvas.
this.DynamicRenderer = customRenderer;
}
protected override void OnStrokeCollected(InkCanvasStrokeCollectedEventArgs e)
{
// Remove the original stroke and add a custom stroke.
this.Strokes.Remove(e.Stroke);
CustomStroke customStroke = new CustomStroke(e.Stroke.StylusPoints);
this.Strokes.Add(customStroke);
// Pass the custom stroke to base class' OnStrokeCollected method.
InkCanvasStrokeCollectedEventArgs args =
new InkCanvasStrokeCollectedEventArgs(customStroke);
base.OnStrokeCollected(args);
}
}
En InkCanvas kan ha mer än en DynamicRenderer. Du kan lägga till flera DynamicRenderer objekt i InkCanvas genom att lägga till dem i egenskapen StylusPlugIns.
Slutsats
Du kan anpassa utseendet på pennanteckningar genom att härleda dina egna DynamicRenderer, Strokeoch InkCanvas-klasser. Tillsammans säkerställer dessa klasser att utseendet på penndraget är konsekvent när användaren ritar det och efter att det har registrerats.
Se även
.NET Desktop feedback