I asked a question in Cancel touch event on InkCanvas (.Net Framework) and didn't got an answer, so I tried to set the InkCanvas
to HitTestVisible
to false
and get the StylusPoints
over an API of the driver. These points are now manually put into Stroke
s and then inside a bound StrokeCollection
. This way, I get the points only from the stylus and not from touch or mouse (I know UWP InkCanvas
can do this by default, but WPF is sadly too old and didn't got a correct support from Microsoft).
But I have a problem regarding the speed of this method. I make a Stroke
out of every point (and the point before) and put them inside the StrokeCollection
. This leads to a "slow" Stroke
. If I write something it is only shown by around 3/4 when I already completed it with the pen and is then completly shown half a second later. Do you have any ideas on how to make this faster, so that it looks like a normal use of the InkCanvas
? Alternatively the question from before could be answered ;)
This is my code:
private void TabLib_DataReceived(object sender, EventArgs e)
{
float pressureFactor = e.pressure / 1024f;
StylusPoint newPoint = new StylusPoint()
{
PressureFactor = pressureFactor,
X = e.xPos,
Y = e.yPos
};
if (pressureFactor == 0) // that means the pen has left or entered the tablet
{
_oldPressurePoint = newPoint;
return;
}
StylusPointCollection pointList = new StylusPointCollection();
pointList.Add(_oldPressurePoint);
pointList.Add(newPoint);
Stroke stroke = new Stroke(pointList, _penDrawingAttributes);
// used a dispatcher begininvoke because of DrawnStrokes are bound to the UI thread.
_tabletWindow.Dispatcher.BeginInvoke(new Action<Stroke>((newStroke) =>
{
DrawnStrokes.Add(newStroke); // DrawnStrokes is the bound StrokeCollection
}), stroke);
_oldPressurePoint = newPoint;
}
I also thought about creating one stroke and only add the points, but this seems not to work. If you already added a stroke, you cannot add points to this stroke, can you?
CodePudding user response:
You should create a new Stroke only when necessary, and add points to the StylusPoints collection of the current Stroke.
Here is a smoothly working example that creates stroke data from mouse input on a Canvas overlay over an InkCanvas.
<Grid>
<InkCanvas x:Name="inkCanvas" IsHitTestVisible="False"/>
<Canvas Background="Transparent"
MouseLeftButtonDown="CanvasMouseLeftButtonDown"
MouseLeftButtonUp="CanvasMouseLeftButtonUp"
MouseMove="CanvasMouseMove"/>
</Grid>
with this code behind:
private Stroke stroke;
private void CanvasMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var pos = e.GetPosition(inkCanvas);
var points = new StylusPointCollection
{
new StylusPoint(pos.X, pos.Y)
};
stroke = new Stroke(points, inkCanvas.DefaultDrawingAttributes);
inkCanvas.Strokes.Add(stroke);
}
private void CanvasMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
stroke = null;
}
private void CanvasMouseMove(object sender, MouseEventArgs e)
{
if (stroke != null)
{
var pos = e.GetPosition(inkCanvas);
stroke.StylusPoints.Add(new StylusPoint(pos.X, pos.Y));
}
}