WPF inkcavas 保存笔迹部分

发布时间 2023-09-07 11:14:02作者: 多见多闻
this.inkCanv.Strokes.Save(file);

And that's enough to save all the information needed to restore the Ink at a later time

Save Ink as a bitmap

Saving the Ink as a Bitmap is a little trickier, but not impossible. We simply use 3 nice objects RenderTargetBitmap,BmpBitmapEncoder and BitmapFrame in the manner shown below:

int marg = int.Parse(this.inkCanv.Margin.Left.ToString());
RenderTargetBitmap rtb = 
        new RenderTargetBitmap((int)this.inkCanv.ActualWidth - marg,
                (int)this.inkCanv.ActualHeight - marg, 0, 0, 
            PixelFormats.Default);
rtb.Render(this.inkCanv);
BmpBitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(rtb));
encoder.Save(file);
file.Close();

It should come as no surprise that to load some Ink from a file its just the opposite of saving a file. As before we simply use a stream. In the attached app, I create a new file format called "Ink Serialized Format", but you can use whatever you like.

this.inkCanv.Strokes = new StrokeCollection(file);
In order to actually cut the Ink, you must Select some Ink to cut. This can be done in 2 ways, you may either use the Select button (this will be discussed here or the current stylus may be changed to be in select mode. This is also discussed in more detail here.

For now I'm going to assume that there is at least some Ink selected. You will be able to see the selected Ink as there will be a bounding rectangle with resize handles surrounding the Ink, as shown in the figure above. So once you've got some ink selected, you will be able to Cut it; it's very easy.

if (this.inkCanv.GetSelectedStrokes().Count > 0)
    this.inkCanv.CutSelection();

Copy Ink

Copying Ink is almost the same as Cutting it (Assuming you have some Ink selected), we simply use the CopySelection method of the InkCanvas instead of the CutSelection

if (this.inkCanv.GetSelectedStrokes().Count > 0)
    this.inkCanv.CopySelection();

Paste Ink

Pasting Ink is almost as easy (Assuming you have some Ink selected), let's have a look at that.

if (this.inkCanv.CanPaste())
    this.inkCanv.Paste();

Delete Ink

Deleting Ink is also very simple (Assuming you have some Ink selected), just check that there are some Strokes to remove, and remove them.

if (this.inkCanv.GetSelectedStrokes().Count > 0)
{
    foreach (Stroke strk in this.inkCanv.GetSelectedStrokes())
        this.inkCanv.Strokes.Remove(strk);
}

Select Ink

Recall earlier for the Select Cut, Copy, Paste And Delete operations, we had to actually have some Ink selected. Well how do we select some Ink. As I stated that this can be done in 2 ways, you may either use the Select button (this option) or the current stylus may be changed to be in select mode. So let's have a look at how to select all Ink. It's very easy:

this.inkCanv.Select(this.inkCanv.Strokes);

Format Ink

Formatting Ink relies on you first having selected some Ink to format. So assuming you have some Ink (Strokes) selected when you use the Format Ink button, you will be shown the color picker window as shown below in the Stylus Color section, that window will enable you to change the Strokes attributes.

The code for the Format button is simply going to try and get the color of the 1st Stroke, and then show the dialog window where we can pick a new color for the selected Strokes.

StylusSettings dlg = new StylusSettings();
dlg.Owner = this;

// Try getting the DrawingAttributes of the first selected stroke.
StrokeCollection strokes = this.inkCanv.GetSelectedStrokes();

if (strokes.Count > 0)
    dlg.DrawingAttributes = strokes[0].DrawingAttributes;
else
    dlg.DrawingAttributes = this.inkCanv.DefaultDrawingAttributes;

if ((bool)dlg.ShowDialog().GetValueOrDefault())
{
    // Set the DrawingAttributes of all the selected strokes.
    foreach (Stroke strk in strokes)
        strk.DrawingAttributes = dlg.DrawingAttributes;
}

Stylus color

In order for the user to control what color and how the Ink should be applied there is a second XAML window that is used, this is called "StylusSettings.xaml" and it contains a UniformGrid control with buttons which simply have their backgrounds set to a particular Brush color out of the collection of System.Brushes.

The iteration of the System.Brushes is done using Reflection.

C#
private void createGridOfColor()
{
    PropertyInfo[] props = typeof(Brushes).GetProperties(BindingFlags.Public |
                                          BindingFlags.Static);
    // Create individual items
    foreach (PropertyInfo p in props)
    {
        Button b = new Button();
        b.Background = (SolidColorBrush)p.GetValue(null, null);
        b.Foreground = Brushes.Transparent;
        b.BorderBrush=Brushes.Transparent;
        b.Click += new RoutedEventHandler(b_Click);
        this.ugColors.Children.Add(b);
    }
}

Also this page is responsible for showing and setting the current Ink values that will be used for drawing with. This is achieved by the use of a nice class called DrawingAttributes which can be both retrieved and set on the InkCanvas

C#
public DrawingAttributes DrawingAttributes
{
    set
    {
        chkPressure.IsChecked = value.IgnorePressure;
        chkHighlight.IsChecked = value.IsHighlighter;
        penWidth = value.Width;
        penHeight = value.Height;
        currColor = value.Color;
    }
    get
    {
        DrawingAttributes drawattr = new DrawingAttributes();
        drawattr.IgnorePressure = (bool)chkPressure.IsChecked;
        drawattr.Width=penWidth;
        drawattr.Height = penHeight;
        drawattr.IsHighlighter = (bool)chkHighlight.IsChecked;
        drawattr.Color = currColor;
        return drawattr;
    }
}