【问题标题】:Highlighter Ink Strokes Not Rendering onto Canvas Control荧光笔墨水笔触未渲染到画布控件上
【发布时间】:2021-06-21 00:07:03
【问题描述】:

我正在尝试使用“InkToolbar”和“InkCanvas”来实现墨迹书写功能。我也希望能够访问墨水笔触,因此我还激活了 InkCanvas 上的自定义干燥功能。

钢笔墨迹和铅笔墨迹在画布控件上正确呈现,但荧光笔描边未在画布控件上呈现(不可见)。

我也尝试了这些解决方案,但问题仍然存在, Save Windows Ink as transparent PNG image - missing highlighter strokes

XAML 代码

<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>

代码背后

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();
    }
}

我不确定这里有什么问题。有人可以指出我正确的方向吗?非常感谢任何帮助。

谢谢

【问题讨论】:

  • 我猜这可能与绘制荧光笔墨水的绘图表面背景有关,尝试将画布控件背景设置为与使用图像刷Background = new ImageBrush { ImageSource = image.Source }的图像相同但仍然没有运气。
  • 我发现的一个解决方法是设置画布控件的清晰颜色,如CanvasControl = new CanvasControl() { Height = viewport.Height, Width = viewport.Width, ClearColor = Color.FromArgb(100, 255, 255, 255) };,但它在内容顶部绘制了一个褪色层,看起来有点不合适。有没有其他方法可以做到这一点?
  • 你提供的代码我已经测试过了。在代码 InkSynchronizer.EndDry(); 处发生 System.InvalidOperationException。我注释了这行代码,然后应用程序就可以正常运行了。在我的测试中,highliter 墨水可以呈现在所选图像上。我对“但荧光笔笔划未在画布控件上呈现(不可见)”这句话感到困惑。您能否详细描述您的预期行为?
  • 有趣的是,我将仅与墨水绘图场景相关的代码放入问题中,而错过了将InkSynchronizer.BeginDry(); 放入问题中。我像您一样评论了 EndDry 行,它导致了我想要的行为。我猜不使用 InkSynchronizer 解决了这个问题。您可以发布答案以便我将其标记为已修复吗? @YanGu-MSFT

标签: c# uwp uwp-xaml inkcanvas win2d


【解决方案1】:

我注意到您在代码中使用了InkSynchronizer.EndDry 方法,但没有使用InkSynchronizer.BeginDry 方法。通过测试,在代码InkSynchronizer.EndDry();处有一个System.InvalidOperationException。然后我对这行代码进行注释,应用程序可以按照您的预期正常运行。而且我还尝试在InkSynchronizer.EndDry 方法之前添加InkSynchronizer.BeginDry 方法,它也可以。因此,您可能需要在您的应用中删除InkSynchronizer.EndDry 方法的使用,或添加InkSynchronizer.BeginDry 方法的使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-31
    • 1970-01-01
    • 2010-11-12
    • 2012-07-31
    相关资源
    最近更新 更多