如何在 C# 中使用 inkcanvas 创建线帽?我也希望这条线只在 XY 方向绘制,而不是在 XZ 或 YZ 方向绘制

问题描述

我创建一条线的工作是:

XAML 代码

<ViewBox x:Name="Img_VB"
         HorizontalAlignment="Center" 
         VerticalAlignment="Top" 
         Stretch="Uniform">
    <ScrollViewer x:Name="rootScrollViewer" 
                  ZoomMode="Enabled" MaxZoomFactor="5" MinZoomFactor="0.5"
                  HorizontalScrollMode="Auto" HorizontalScrollBarVisibility="Auto"
                  VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto">
        <Grid x:Name="img_grid" 
          Width="600"
          Height="800" 
          Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" 
          ManipulationMode="Scale">
            <Image 
               x:Name="RoomPlan_Img" 
               VerticalAlignment="Stretch" 
               HorizontalAlignment="Stretch"
               Stretch="Uniform" 
               Height="800" 
               ManipulationMode="Scale">
            </Image>
            <Canvas x:Name="selectionCanvas" 
                Width="600" 
                Background="Transparent" 
                Height="800" >
            </Canvas>
            <InkCanvas x:Name="inker" />
            <InkToolbar x:Name="img_inktoolbar" 
                    InitialControls="None"
                    TargetInkCanvas="{x:Bind inker}" 
                    VerticalAlignment="Top" >
            </InkToolbar>
        </Grid>
    </ScrollViewer>
</ViewBox>

背后的代码

public RoomPlanEditCD()
{
    this.InitializeComponent();

    inker.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Touch;
    inker.InkPresenter.UnprocessedInput.Pointerpressed += StartLine;
    inker.InkPresenter.UnprocessedInput.PointerMoved += ContinueLine;
    inker.InkPresenter.UnprocessedInput.PointerReleased += CompleteLine;
    inker.InkPresenter.InputProcessingConfiguration.RightDragAction = InkInputRightDragAction.LeaveUnprocessed;
}

private void StartLine(InkUnprocessedInput sender,PointerEventArgs args)
{
    line = new Line();
    line.X1 = args.CurrentPoint.RawPosition.X;
    line.Y1 = args.CurrentPoint.RawPosition.Y;
    line.X2 = args.CurrentPoint.RawPosition.X;
    line.Y2 = args.CurrentPoint.RawPosition.Y;

    line.stroke = new SolidColorBrush(Colors.Black);
    line.strokeThickness = 2;
    selectionCanvas.Children.Add(line);
}

private void ContinueLine(InkUnprocessedInput sender,PointerEventArgs args)
{
    line.X2 = args.CurrentPoint.RawPosition.X;
    line.Y2 = args.CurrentPoint.RawPosition.Y;
}

private void CompleteLine(InkUnprocessedInput sender,PointerEventArgs args)
{
    List<InkPoint> points = new List<InkPoint>();
    InkstrokeBuilder builder = new InkstrokeBuilder();

    InkPoint pointOne = new InkPoint(new Point(line.X1,line.Y1),0.5f);
    points.Add(pointOne);
    InkPoint pointTwo = new InkPoint(new Point(line.X2,line.Y2),0.5f);
    points.Add(pointTwo);
    Inkstroke stroke = builder.CreatestrokeFromInkPoints(points,System.Numerics.Matrix3x2.Identity);
    InkDrawingAttributes ida = inker.InkPresenter.copyDefaultDrawingAttributes();
    stroke.DrawingAttributes = ida;
    inker.InkPresenter.strokeContainer.Addstroke(stroke);
    selectionCanvas.Children.Remove(line);
}

private async void ChooseFileClick(ContentDialog sender,ContentDialogButtonClickEventArgs args)
{
    //some code to pick a file create a stream of it and show it in the Image Box

    RoomPlan_Img.source = bmpimage;
    _ = await ShowAsync();
}

private async void SaveEditedWorkClick(ContentDialog sender,ContentDialogButtonClickEventArgs args)
{
    img_inktoolbar.Visibility = Visibility.Collapsed;
    rendertargetBitmap bitmap = new rendertargetBitmap();
    await bitmap.RenderAsync(img_grid);
    var pixelBuffer = await bitmap.GetPixelsAsync();
    byte[] pixels = pixelBuffer.ToArray();
    var displayinformation = displayinformation.GetForCurrentView();
    StorageFolder pictureFolder = KNownFolders.SavedPictures;
    var file = await pictureFolder.CreateFileAsync("test2.png",CreationCollisionoption.ReplaceExisting);
    using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
    {
        var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId,stream);
        encoder.SetPixelData(BitmapPixelFormat.Bgra8,BitmapAlphaMode.Ignore,(uint)bitmap.PixelWidth,(uint)bitmap.PixelHeight,displayinformation.RawDpiX,displayinformation.RawDpiY,pixels);
        await encoder.FlushAsync();
    }
    inker.InkPresenter.strokeContainer.Clear();
    RoomPlan_Img.source = null;
    img_inktoolbar.Visibility = Visibility.Visible;
}

通过这项工作,我能够在图像上创建一条直线并将工作保存为 png 文件。我需要的是能够在绘制的线的末尾用一个三角形画线,

我尝试过的工作:

line.strokeEndLineCap = PenLineCap.Triangle;

但仍然画了一条简单的线,而不是一条带箭头的三角形线

我无法弄清楚的另一件事是如何仅在 XY 方向上画一条线,即

example

如果用户试图在 XZ 或 YZ 方向绘制一条线,那应该是不可能的。

感谢任何形式的帮助 谢谢

解决方法

您看到的线条不是 Line 对象。实际上,它们实际上是 InkCanvas 控制区域中显示的墨迹笔划。您为生成线注册的那些指针事件无效,例如 StartLine、ContinueLine、CompleteLine。线对象为空。

在 InkCanvas 中的“线”上添加线帽很难,因为它不是一条线,它是一条墨迹笔划路径。我建议你可以通过 WriteableBitmap 和 Win2D 而不是 InkCanvas 来做到这一点。可以把位图当做背景图层,在上面画一些东西,比如带linecap的线,然后把所有的图层都输出到一个新的WriteableBitmap上。请参阅this document以获取更多信息。