I'm trying to implement inking functionality using 'InkToolbar' & 'InkCanvas'. I want to be able to access the ink strokes as well, so I have activated custom drying on the InkCanvas as well.
Pen ink strokes & pencil ink strokes render properly on the canvas control but highlighter strokes are not rendering (not visible) on the canvas control.
I tried these solutions also but still the issue is there, Save Windows Ink as transparent PNG image - missing highlighter strokes
XAML Code
<Grid x:Name="container" Background="#FF282828">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<InkToolbar x:Name="inkToolbar" InitialControls="None" Grid.Row="0">
<InkToolbarBallpointPenButton />
<InkToolbarPencilButton />
<InkToolbarHighlighterButton />
<InkToolbarEraserButton />
</InkToolbar>
<ScrollViewer ZoomMode="Enabled" Background="DarkGray" Grid.Row="1" x:Name="scrollViewer" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" MinZoomFactor="0.5" Height="Auto">
<Grid x:Name="viewport" VerticalAlignment="Top">
<Border x:Name="viewportBorder" Background="White" BorderThickness="15, 15, 15, 15" BorderBrush="#FF353334" />
</Grid>
</ScrollViewer>
</Grid>
Code Behind
public sealed partial class MainPage : Page
{
private Canvas SelectCanvas;
private InkCanvas InkCanvas;
private CanvasControl CanvasControl;
private InkSynchronizer InkSynchronizer;
private List<InkStrokeContainer> InkStrokeContainers = new List<InkStrokeContainer>();
public MainPage()
{
this.InitializeComponent();
InitViweport().GetAwaiter();
}
private async Task InitViweport()
{
FileOpenPicker openPicker = new FileOpenPicker
{
SuggestedStartLocation = PickerLocationId.PicturesLibrary,
ViewMode = PickerViewMode.Thumbnail
};
// Filter to include a sample subset of file types.
openPicker.FileTypeFilter.Clear();
openPicker.FileTypeFilter.Add(".bmp");
openPicker.FileTypeFilter.Add(".png");
openPicker.FileTypeFilter.Add(".jpeg");
openPicker.FileTypeFilter.Add(".jpg");
var file = await openPicker.PickSingleFileAsync();
if (file != null)
{
// Open a stream for the selected file.
IRandomAccessStream fileStream = await file.OpenAsync(FileAccessMode.Read);
var bitmapImage = new BitmapImage();
bitmapImage.SetSource(fileStream);
viewport.Width = bitmapImage.PixelWidth;
viewport.Height = bitmapImage.PixelHeight;
using (var stream = await file.OpenReadAsync())
{
WriteableBitmap bitmap = new WriteableBitmap(bitmapImage.PixelWidth, bitmapImage.PixelHeight);
await bitmap.SetSourceAsync(stream);
var image = new Image();
image.Source = bitmap;
viewport.Children.Add(image);
}
}
AddCanvases();
}
private void AddCanvases()
{
SelectCanvas = new Canvas
{
Height = viewport.Height,
Width = viewport.Width
};
InkCanvas = new InkCanvas
{
Width = viewport.Width,
Height = viewport.Height
};
inkToolbar.TargetInkCanvas = InkCanvas;
CanvasControl = new CanvasControl()
{
Height = viewport.Height,
Width = viewport.Width,
Background = new SolidColorBrush(Colors.Transparent)
};
CanvasControl.Draw += CanvasControlDraw;
InkSynchronizer = InkCanvas.InkPresenter.ActivateCustomDrying();
InkCanvas.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Pen | CoreInputDeviceTypes.Touch;
InkCanvas.InkPresenter.StrokesCollected += InkPresenter_StrokesCollected;
Canvas.SetZIndex(InkCanvas, 5);
Canvas.SetZIndex(SelectCanvas, 2);
viewport.Children.Add(SelectCanvas);
viewport.Children.Add(CanvasControl);
viewport.Children.Add(InkCanvas);
}
private void CanvasControlDraw(CanvasControl sender, CanvasDrawEventArgs args) => DrawInk(args.DrawingSession);
private void DrawInk(CanvasDrawingSession session)
{
foreach (var container in InkStrokeContainers)
{
var strokes = container.GetStrokes();
using (var list = new CanvasCommandList(session))
{
using (var listSession = list.CreateDrawingSession())
listSession.DrawInk(strokes);
using (var shadowEffect = new ShadowEffect { ShadowColor = Colors.DarkGray, Source = list })
session.DrawImage(shadowEffect, new Vector2(2, 2));
}
session.DrawInk(strokes);
}
}
private void InkPresenter_StrokesCollected(InkPresenter sender, InkStrokesCollectedEventArgs args)
{
var strokeContainer = new InkStrokeContainer();
strokeContainer.AddStrokes(from stroke in args.Strokes select stroke.Clone());
InkStrokeContainers.Add(strokeContainer);
InkSynchronizer.EndDry();
CanvasControl.Invalidate();
}
}
I'm not sure what the issue here. Could someone please point me in the right direction? Any help is much appreciated.
Thanks
I noticed that you are using InkSynchronizer.EndDry
method, but not using InkSynchronizer.BeginDry
method in your code. By testing, there is an System.InvalidOperationException
occurs at the code InkSynchronizer.EndDry();
. Then I comment the line of code and the app could run well just as you expected. And I also try to add the InkSynchronizer.BeginDry
method before the InkSynchronizer.EndDry
method, it also works. Therefore, you may need to delete the usage of InkSynchronizer.EndDry
method, or add the usage of InkSynchronizer.BeginDry
method in your app.