Posted by: Cirilo Meggiolaro | 01/24/2009

Tip of the day #102 – InkCanvas control (WPF)

The controls for WPF (Windows Presentation Foundation) are really cool and so easy to work with. Today we are going to take a look on the InkCanvas control that gives you an area like a board where you may draw or handwrite. You may save the content of an InkCanvas to a file and load an existing file to your current InkCanvas.

InkCanvas control

The InkCanvas control is an area where you may paint with brushes. Each draw that you make on InkCanvas is known as a stroke.

The main properties are:

  • InkCanvasEditingMode ActiveEditingMode: Read-only property that retrieves the current editing mode of the InkCanvas;
  • Brush Background: Gets or sets a Brush used to fill the border area of the InkCanvas;
  • DrawingAttributes DefaultDrawingAttributes: Gets or sets the drawing attributes for a new ink stroke. Existing strokes on the InkCanvas are not replaced;
  • StylusPointDescription DefaultStylusPointDescription: Gets or sets the stylus point description for the InkCanvas;
  • InkCanvasEditingMode EditingMode: Gets or sets the user editing mode. Available options are Ink, GestureOnly, InkAndGesture, Select, EraseByPoint, EraseByStroke and None;
  • StylusShape EraserShape: Gets or sets the StylusShape used to point-erase ink from the InkCanvas;
  • bool MoveEnabled: Gets or sets a Boolean value that indicates whether ink strokes may be moved by the user;
  • IEnumerable<InkCanvasClipboardFormat> PreferredPasteFormats: Gets or sets formats that can be pasted onto the InkCanvas;
  • bool ResizeEnabled: Gets or sets a Boolean value that indicates whether the user can resize selected strokes;
  • StrokeCollection Strokes: Gets or sets the content of the InkCanvas control using a collection of Strokes objects.

Example

In this example we are going to create a WPF application with an InkCanvas control and we are going to control the brush height, color, move and resize strokes individually.

How to…

  • Open Visual Studio 2008;
  • Create a new WPF application;
  • Add an InkCanvas control to your window and name it myInkCanvas;
  • Add a button, name it btnSave, set its content property to Save;
  • Double-click on btnSave control to add a click event for it;
  • Add a button, name it btnLoad, set its content property to Load;
  • Double-click on btnLoad control to add a click event for it;
  • Add a button, name it btnClear, set its content property to Clear;
  • Double-click on btnClear control to add a click event for it;
  • Add a combobox, name it cboColor. Add the following options to it: Black, Blue, Green, Red, Yellow;
  • Double-click on cboColor control to add a SelectionChanged event;
  • Add a combobox, name it cboBrushSize and add the following options to it: 1, 2, 4, 6, 8, 10;
  • Double-click on cboBrushSize control to add a SelectionChanged event;
  • Add a radiobutton, name it radDrawingMode and set its content to Drawing;
  • Add a Checked event to radDrawingMode control;
  • Add a radiobutton, name it radSelectMode and set its content to Select;
  • Add a Checked event to radSelectMode control. You may use the same you created on the previous step;
  • The window will be similar to the following:
Picture 1 - Window prototype

Picture 1 - Window prototype

  • The XAML will be similar to the following:

<Window x:Class=”Tip102.Window1″
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation&#8221;
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml&#8221;
Title=”Tip #102 – InkCanvas Control” Height=”263″ Width=”552″>
  <Grid>
    <InkCanvas Margin=”4,4,152,5″ Name=”myInkCanvas” ClipToBounds=”True” Background=”White”></InkCanvas>
    <Button Margin=”0,77,7,0″ Name=”btnClear” VerticalAlignment=”Top” Content=”Clear” Click=”btnClear_Click” HorizontalAlignment=”Right” Width=”75″></Button>
    <Button Margin=”0,106,7,0″ Name=”btnSave” VerticalAlignment=”Top” HorizontalAlignment=”Right” Width=”75″ Content=”Save” Click=”btnSave_Click”></Button>
    <Button Margin=”0,134,7,0″ Name=”btnLoad” VerticalAlignment=”Top” Content=”Load” Click=”btnLoad_Click” HorizontalAlignment=”Right” Width=”75″></Button>
    <ComboBox HorizontalAlignment=”Right” Margin=”0,12,7,0″ Name=”cboBrushSize” VerticalAlignment=”Top” Width=”66″ SelectionChanged=”cboBrushSize_SelectionChanged”>
      <ComboBoxItem>1</
ComboBoxItem>
      <ComboBoxItem IsSelected=”True”>2</
ComboBoxItem>
      <
ComboBoxItem>4</ComboBoxItem>
      <
ComboBoxItem>6</ComboBoxItem>
      <
ComboBoxItem>8</ComboBoxItem>
      <
ComboBoxItem>10</ComboBoxItem>
    </ComboBox>
    <Label HorizontalAlignment=”Right” Margin=”0,11,66,0″ Name=”lblBrushSize” VerticalAlignment=”Top” Width=”70″ Content=”Brush Size:”></Label>
    <Label HorizontalAlignment=”Right” Margin=”0,43,73,0″ Name=”lblColor” VerticalAlignment=”Top” Width=”61″ Content=”Color:”></Label>
    <ComboBox HorizontalAlignment=”Right” Margin=”0,43,7,0″ Name=”cboColor” VerticalAlignment=”Top” Width=”85″ SelectionChanged=”cboColor_SelectionChanged”>
      <
ComboBoxItem IsSelected=”True”>Black</ComboBoxItem>
      <
ComboBoxItem>Blue</ComboBoxItem>
      <
ComboBoxItem>Green</ComboBoxItem>
      <
ComboBoxItem>Red</ComboBoxItem>
      <
ComboBoxItem>Yellow</ComboBoxItem>
    </ComboBox>
    <GroupBox Header=”Mode” Height=”57″ HorizontalAlignment=”Right” Margin=”0,0,7,5″ Name=”groupBox1″ VerticalAlignment=”Bottom” Width=”139″>
      <Grid Width=”117″>
        <RadioButton Margin=”6,6,0,0″ Name=”radDrawingMode” HorizontalAlignment=”Left” Width=”58″ Height=”24.723″ VerticalAlignment=”Top” GroupName=”mode” IsChecked=”True” Checked=”RadMode_Checked” Content=”Drawing”></RadioButton>
        <RadioButton Margin=”0,6,-5,7″ Name=”radSelectMode” HorizontalAlignment=”Right” Width=”52″ GroupName=”mode” Checked=”RadMode_Checked” Content=”Select”></RadioButton>
      </Grid>
    </GroupBox>
  </Grid>
</Window>

  • Go to the code-behind and look up the event click from the btnClear control. We are going to use this event to clear the InkCanvas. Once we add a new stroke to Strokes collection every time we draw something, we are going to call the method Clear() from the Strokes collection to remove all the drawings as following:

myInkCanvas.Strokes.Clear();

  • Look up the event click of the btnSave button. The Strokes collection has a method called Save that accepts a stream object to save all the inks to it. So, declare and instantiate a new FileStream object, set the filename to myInk.ink and the FileMode to Create. Call the Save method from Strokes collection passing the stream as parameter and close the stream;

FileStream stream = new FileStream(“myInk.ink”, FileMode.Create);
myInkCanvas.Strokes.Save(stream);
stream.Close();

  • Lookup the event click on the btnLoad button. We are going to add code to load an existing file and display on the InkCanvas. To accomplish that, add a FileStream object pointing to the same file we saved on the previous step. Instantiate a new StrokeCollection object passing the stream as parameter and assign it to the Strokes collection from our InkCanvas control. Don’t forget to close the FileStream;

FileStream stream = new FileStream(“myInk.ink”, FileMode.Open);
myInkCanvas.Strokes = new System.Windows.Ink.StrokeCollection(stream);
stream.Close();

  • Lookup the SelectionChanged event for the cboBrushSize control. The InkCanvas control contains a property called DefaultDrawingAttributes from the DrawingAttributes type. This type contains several properties that you may use to set elements such as brush size, color and so on. For this step we need to set both Width and Height to the value selected on the cboBrushSize control;

myInkCanvas.DefaultDrawingAttributes.Width = Convert.ToDouble(((ComboBoxItem)cboBrushSize.SelectedItem).Content);
myInkCanvas.DefaultDrawingAttributes.Height = Convert.ToDouble(((ComboBoxItem)cboBrushSize.SelectedItem).Content);

  • Lookup the SelectionChanged event for the cboColor control. WPF does not have a color picker dialog so I am just using this combo to show you how to set the brush color. The Color property is also available under the DefaultDrawingAttributes object from the InkCanvas control;

if (((ComboBoxItem)cboColor.SelectedItem).Content.ToString() == “Black”)
    myInkCanvas.DefaultDrawingAttributes.Color = Colors.Black;

  • The last code step is to set the InkCanvas edit mode to Ink when the radio button radDrawingMode is checked. When the radio button radSelectMode is checked we are going to set the edit mode to Select so you are going to be able to select a drawing you’ve done and resize or move it;

if (radDrawingMode.IsChecked.Value == true)
    myInkCanvas.EditingMode = InkCanvasEditingMode.Ink;
else if (radSelectMode.IsChecked.Value == true)
    myInkCanvas.EditingMode = InkCanvasEditingMode.Select;

  • Compile and run the application.

The final code must be similar to the following:

private void btnClear_Click(object sender, RoutedEventArgs e)
{
    /// Removes all strokes from the InkCanvas.
    myInkCanvas.Strokes.Clear();
}

private void btnSave_Click(object sender, RoutedEventArgs e)
{
    /// Creates a FileStream object.
    FileStream stream = new FileStream(“myInk.ink”, FileMode.Create);

    /// Saves the InkCanvas content to the stream.
    myInkCanvas.Strokes.Save(stream);

    /// Closes the stream.
    stream.Close();
}

private void btnLoad_Click(object sender, RoutedEventArgs e)
{
    /// Creates a FileStream from an existing file.
    FileStream stream = new FileStream(“myInk.ink”, FileMode.Open);

    /// Creates a new StrokeCollection object from the stream
    /// and assign it to the InkCanvas Strokes collection.

    myInkCanvas.Strokes = new System.Windows.Ink.StrokeCollection(stream);

    /// Closes the stream.
    stream.Close();
}

private void cboBrushSize_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (cboBrushSize.Items.Count > 0 && ((ComboBoxItem)cboBrushSize.SelectedItem).Content != null)
    {
        /// Sets the brush size.
        myInkCanvas.DefaultDrawingAttributes.Width = Convert.ToDouble(((ComboBoxItem)cboBrushSize.SelectedItem).Content);
myInkCanvas.DefaultDrawingAttributes.Height = Convert.ToDouble(((ComboBoxItem)cboBrushSize.SelectedItem).Content);
    }
}

private void cboColor_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (cboColor.Items.Count > 0 && ((ComboBoxItem)cboColor.SelectedItem).Content != null)
    {
        /// Sets the brush color based on the selected color.
        if (((ComboBoxItem)cboColor.SelectedItem).Content.ToString() == “Black”)
            myInkCanvas.DefaultDrawingAttributes.Color = Colors.Black;
        else if (((ComboBoxItem)cboColor.SelectedItem).Content.ToString() == “Blue”)
            myInkCanvas.DefaultDrawingAttributes.Color = Colors.Blue;
        else if (((ComboBoxItem)cboColor.SelectedItem).Content.ToString() == “Green”)
            myInkCanvas.DefaultDrawingAttributes.Color = Colors.Green;
        else if (((ComboBoxItem)cboColor.SelectedItem).Content.ToString() == “Red”)
            myInkCanvas.DefaultDrawingAttributes.Color = Colors.Red;
        else if (((ComboBoxItem)cboColor.SelectedItem).Content.ToString() == “Yellow”)
            myInkCanvas.DefaultDrawingAttributes.Color = Colors.Yellow;
    }
}

private void RadMode_Checked(object sender, RoutedEventArgs e)
{
    /// Sets the editing mode to Ink or Select.
    if (radDrawingMode.IsChecked.Value == true)
        myInkCanvas.EditingMode = InkCanvasEditingMode.Ink;
    else if (radSelectMode.IsChecked.Value == true)
        myInkCanvas.EditingMode = InkCanvasEditingMode.Select;
}

Picture 2 - The InkCanvas control in action.

Picture 2 - The InkCanvas control in action.

Picture 3 - A stroke selected.

Picture 3 - A stroke selected.

Picture 4 - The stroke on a new place.

Picture 4 - The stroke on a new place.

Advertisements

Responses

  1. Nice and simple. Thanks.

  2. thanks nice explanation


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: