none
WPF InkCanvas: Rectangle Stroke Skewed after Rotate, Resize and Back to original positon RRS feed

  • Question

  • Hi Team,

    I am developing Drawing tool using WPF inkcanvas. The goal is to rotate and resize independently X & Y axis and both axis as well. However, the shape should not be changed.

    1. I had Drawn Rectangle using ink mode/Generate StrokeCollection points and assign the collection to the inkcanvas strokes property.

    2. Select the rectangle and Rotate at an angle(say 30 deg) using RotateAt method of Matrix class

    3. Resize the Rectangle(NOT proportional) by dragging resize handle on the default selected stroke adorner layer.

    4. Rotate back to the previous angle(say -30 deg)

    Now, the Rectangle shape is deformed/skewed.

    Query 1: How should I retain the shape after doing the above steps?

    I even tried with custom adorner layer. However, the default selected rect bounds is still visible.

    Query 2: Is it possible to make default rect bounds invisible still stroke selected?

    Quer 3: Is there any solution to achieve this using custom Adorner Layer? If so , please provide pseudo/sample code for this.

     Kindly help me to get rid of this issue.

    Thanks in Advance.


    Ravichandran, O.S.

    Monday, June 11, 2012 7:39 AM

All replies

  • Hi,

    In addition to the above points, i am explaining the problem in other words,

    I am developing Drawing tool using WPF inkcanvas. The goal is to rotate and resize independently X & Y axis and both axis as well. However, the shape should not be changed.
    Reference code which I follow in my drawing tool is from the link 
    http://msdn.microsoft.com/en-us/library/aa350663.aspx - I used this Adorner class for InkCanvas instead of InkPresenter in the sample code.

    I added the below code in the InkCanvas SelectionChanged event because I want to rotate/resize only the selected strokes
    // Add the rotating strokes adorner to the InkPresenter.
    adornerLayer = AdornerLayer.GetAdornerLayer(inkPresenter1);
    adorner = new RotatingStrokesAdorner(inkPresenter1);

    adornerLayer.Add(adorner);

    By default, there will be Rectangle bounds with 8 resize handle created while selecting the strokes. Also, RotatingStrokesAdorner layer will also be created with thumb for rotate handle.

    What I am doing is that Resize the selected stroke(s) horizontally using the rect bounds handle. Now, Rotate using the Thumb handle to some angle say 45deg. RotatingStrokesAdorner Rearrange the structure. However, default Rectangle bounds changed to fit the rotated stroke size and is NOT rotating(i hope it is the dafault behavior) as RotatingStrokesAdorner. Again resize the same selected stroke(s) as did before. Atlast, rotate it back to original angle (or rotate to -45deg).

    Now, the Rectangle shape is deformed/skewed.

    Query 1: How should I retain the shape after doing the above steps?
    I even tried with custom adorner layer. However, the default selected rect bounds is still visible.
    Query 2: Is it possible to make default rect bounds invisible still stroke selected?
    Query 3: Is there any solution to achieve this using custom Adorner Layer? If so , please provide pseudo/sample code for this.

     Kindly help me to get rid of this issue. Please note that I could find samples using plain canvas. However I want the solution or suggestion to do with InkCanvas and Ink/Strokes.

    Looking forward valuable points.

    Thanks in Advance.


    Ravichandran, O.S.

    Monday, June 11, 2012 7:41 AM
  • Hi Ravichandran,

    So much words may complicate this issue. 

    In short, could you please provide a little simple sample which can repro this issue for us to help you find the root cause of your issue?

    Best regards.

    Tuesday, June 12, 2012 9:46 AM
  • Hi Rosa,

    Sorry for the delay. I was busy to close the project and we mentioned this issue as Known Issue in the release notes and wind up the project.

    It is the time to convey and share my problem and find the solution for this issue.

    As per your request, i am pasting the sample code. Kindly follow the below instructions to reproduce my issue. 

    1. Create a WPF Application Project namely FixSkew.

    2. Copy and Replace the content of MainWindow.xaml and MainWindow.xaml.cs which are provided below.

    3. Build and Run the application. This will opens the Main Window.

    4. Click on the button "Draw Rectangle". This draws the rectangle stroke for you.

    5. Click on the button "Select" and select the rectangle stroke.

    6. Provide an angle in the textbox (say 30) and click Rotate. This rotates the selected stroke to 30 degrees clockwise

    7. Stretch/Resize the rectangle stroke (rotated) either horizontal or vertical.

    8. Now, change the angle with negative value (say -30 as per step 6) and click Rotate.

    In the 7th step, stroke gets skewed and in step 8, it is not retain Rectangle shape.

    ****************** MainWindow.xaml ******************

    <Window x:Class="FixSkew.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <InkCanvas x:Name="inkCanvas" Height="300"></InkCanvas>
            <StackPanel Orientation="Horizontal" Height="50" VerticalAlignment="Bottom">
                <Button x:Name="btnInk" Margin="5" Click="btnInk_Click">Ink Mode</Button>
                <Button x:Name="btnRectangle" Margin="5" Click="btnRectangle_Click">Draw Rectangle</Button>
                <Button x:Name="btnSelect" Margin="5" Click="btnSelect_Click">Select Mode</Button>
                <Button x:Name="btnClear" Margin="5" Click="btnClear_Click">Clear All</Button>
                <TextBlock x:Name="lblAngle" Margin="5 15 5 0">Angle</TextBlock>
                <TextBox x:Name="txtAngle" Width="100" Height="30" />
                <Button x:Name="btnRotate" Margin="5" Click="btnRotate_Click">Rotate</Button>
            </StackPanel>
        </Grid>
    </Window>



    ****************** MainWindow.xaml Ends ******************


    ****************** MainWindow.xaml.cs ******************

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using System.Windows.Ink;

    namespace FixSkew
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }

            private void btnInk_Click(object sender, RoutedEventArgs e)
            {
                inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
            }

            private void btnSelect_Click(object sender, RoutedEventArgs e)
            {
                inkCanvas.EditingMode = InkCanvasEditingMode.Select;
            }

            private void btnClear_Click(object sender, RoutedEventArgs e)
            {
                inkCanvas.Strokes.Clear();
            }

            private void btnRotate_Click(object sender, RoutedEventArgs e)
            {
                int angle = 0;
                if (int.TryParse(txtAngle.Text, out angle))
                {
                    StrokeCollection collecStrokes = inkCanvas.GetSelectedStrokes();
                    Rect selectionBounds = inkCanvas.GetSelectionBounds();
                    if (collecStrokes != null && selectionBounds != null)
                    {
                        Matrix rotationalMatrix = Matrix.Identity;
                        rotationalMatrix.RotateAt(Convert.ToInt32(txtAngle.Text), selectionBounds.Left + selectionBounds.Width / 2, selectionBounds.Top + selectionBounds.Height / 2);
                        inkCanvas.GetSelectedStrokes().Transform(rotationalMatrix, true);
                    }
                }
            }

            private void btnRectangle_Click(object sender, RoutedEventArgs e)
            {
                StylusPoint stylusPoint1 = new StylusPoint(100, 100); //(x1, y1)
                StylusPoint stylusPoint2 = new StylusPoint(100, 150); //(x1, y2)
                StylusPoint stylusPoint3 = new StylusPoint(250, 150); //(x2, y2)
                StylusPoint stylusPoint4 = new StylusPoint(250, 100); //(x2, y1)
                StylusPoint stylusPoint5 = new StylusPoint(100, 100); //(x1, y1)
                StylusPointCollection collecStylusPoint = new StylusPointCollection(new StylusPoint[] { stylusPoint1, stylusPoint2, stylusPoint3, stylusPoint4, stylusPoint5 });

                if (collecStylusPoint.Count > 0)
                {
                    Stroke newStroke = new Stroke(collecStylusPoint);
                    this.inkCanvas.Strokes.Add(newStroke);
                }
            }
        }
    }

    ****************** MainWindow.xaml.cs Ends ******************

    I hope this is simple enough to reproduce my issue. Looking forward favorable reply with issue fixed.

    Thank you,


    Ravichandran, O.S.

    Wednesday, July 4, 2012 1:20 PM