Özel İşleme Mürekkebi
DrawingAttributesBir konturun özelliği, bir konturun boyutunu, rengini ve şeklini belirtmenize olanak tanır, ancak bu görünümü, izin verdiklerinin ötesinde özelleştirmek istediğiniz zamanlar olabilir DrawingAttributes . Havayolu fırçasının, yağ boyanın ve diğer birçok etkilerin görünümünde işleme yaparak mürekkebin görünümünü özelleştirmek isteyebilirsiniz. Windows Presentation Foundation (WPF) özel bir ve nesnesi uygulayarak özel işleme mürekkebinizi sağlar DynamicRenderer Stroke .
Bu konu, aşağıdaki alt bölümleri içerir:
Mimari
Mürekkep işleme iki kez gerçekleşir; bir Kullanıcı bir mürekkep yüzeyine mürekkep yazdığında ve mürekkep etkin yüzeyine vuruş eklendikten sonra yeniden. , DynamicRenderer Kullanıcı tablet kalemini çizim tablasına taşırken mürekkebi işler ve Stroke bir öğeye eklendikten sonra kendisini işler.
Mürekkebi dinamik olarak işlerken uygulanacak üç sınıf vardır.
DynamicRenderer: öğesinden türetilen bir sınıf uygulayın DynamicRenderer . Bu sınıf, StylusPlugIn vuruşu çizilen şekilde işleyen bir özelleşmiş. , DynamicRenderer İşleme ayrı bir iş parçacığında yapılır, bu nedenle uygulama kullanıcı arabirimi (UI) iş parçacığı engellendiğinde bile mürekkep yüzeyi mürekkebi toplayacak şekilde görünür. İş parçacığı modeli hakkında daha fazla bilgi için bkz. mürekkep Iş parçacığı modeli. Bir konturu dinamik olarak işlemeyi özelleştirmek için yöntemini geçersiz kılın OnDraw .
Stroke: öğesinden türetilen bir sınıf uygulayın Stroke . Bu sınıf, StylusPoint bir nesnesine dönüştürüldükten sonra verilerin statik olarak işlenmesinden sorumludur Stroke . DrawCoreKonturun statik işlemenin dinamik işleme ile tutarlı olduğundan emin olmak için yöntemini geçersiz kılın.
InkCanvas: Öğesinden türetilen bir sınıf uygulayın InkCanvas . Özelleştirilmiş özelliğe atayın DynamicRenderer DynamicRenderer . Yöntemi geçersiz kılın OnStrokeCollected ve özelliğe özel bir vuruş ekleyin Strokes . Bu, mürekkebin görünümünün tutarlı olmasını sağlar.
Dinamik bir Işleyici uygulama
DynamicRendererSınıfı standart bir parçası olsa da, WPF daha özelleştirilmiş işleme gerçekleştirmek için, öğesinden türetilmiş DynamicRenderer ve yöntemi geçersiz kıldığınız özelleştirilmiş bir dinamik işleyici oluşturmanız gerekir OnDraw .
Aşağıdaki örnek, DynamicRenderer Doğrusal bir gradyan fırçası efektiyle mürekkep çizen özelleştirilmiş bir şekilde gösterir.
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
Özel konturlar uygulama
Öğesinden türetilen bir sınıf uygulayın Stroke . Bu sınıf, StylusPoint bir nesnesine dönüştürüldükten sonra verileri işlemenin sorumluluğundadır Stroke . DrawCoreAsıl çizimi yapmak için sınıfı geçersiz kılın.
Stroke sınıfınız, yöntemini kullanarak özel verileri de saklayabilir AddPropertyData . Bu veriler, kalıcı olduğunda vuruş verileriyle birlikte depolanır.
StrokeSınıfı isabet testi de gerçekleştirebilir. Ayrıca, geçerli sınıftaki yöntemi geçersiz kılarak kendi isabet testi algoritmanızı da uygulayabilirsiniz HitTest .
Aşağıdaki C# kodu, Stroke StylusPoint verileri 3B vuruş olarak işleyen özel bir sınıfı gösterir.
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
Özel bir InkCanvas uygulama
Özelleştirilmiş ve vuruşlarınızı kullanmanın en kolay yolu, DynamicRenderer Bu sınıfların türediği ve kullandığı bir sınıf uygulamaktır InkCanvas . , InkCanvas DynamicRenderer Kullanıcı çizimi çizerken konturun nasıl işleneceğini belirten bir özelliğine sahiptir.
Özel işleme konturlarına aşağıdakilerden InkCanvas birini yapın:
Öğesinden türetilen bir sınıf oluşturun InkCanvas .
Özelinizi DynamicRenderer InkCanvas.DynamicRenderer özelliğine atayın.
Yöntemini geçersiz kılın OnStrokeCollected . Bu yöntemde, InkCanvas 'a eklenen orijinal vuruşu kaldırın. Ardından özel bir vuruş oluşturun, Strokes özelliği özelliğe ekleyin ve özel konturu içeren yeni bir temel sınıfı çağırın InkCanvasStrokeCollectedEventArgs .
Aşağıdaki C# kodu, InkCanvas özelleştirilmiş DynamicRenderer ve özel vuruşları toplayan özel bir sınıfı gösterir.
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);
}
}
InkCanvas, Birden fazla olabilir DynamicRenderer . DynamicRendererÖzelliğine ekleyerek öğesine birden çok nesne ekleyebilirsiniz InkCanvas StylusPlugIns .
Sonuç
Kendi DynamicRenderer , ve sınıflarınızı türeterek mürekkebin görünümünü özelleştirebilirsiniz Stroke InkCanvas . Bu sınıflar birlikte, Kullanıcı vuruşu çizdiğinde ve toplandıktan sonra konturun görünümünün tutarlı olmasını sağlar.