9

Is it possible to rotate FrameworkElement.Cursor?

My application allows user to rotate objects around their center. Once rotated, default resize cursors appear awkward on top of tilted borders.

Mouse cursor not affected by transform

My first thought was to apply RotateTransform to the Cursor property, but it looks like we can't do that in XAML. Next I tried inheriting from Cursor class, but it looks like MS guys have sealed it.

Another way is to set default cursor to None and use my own image (with transform) and set its position upon MouseMove. I'm not willing to go down that path if there are easier alternatives. Anyone with a good suggestion?

I'm looking for a WPF-only solution if at all possible.

dotNET
  • 33,414
  • 24
  • 162
  • 251
  • 2
    Possible duplicate of [Rotating Cursor According to Rotated TextBox](http://stackoverflow.com/questions/2835502/rotating-cursor-according-to-rotated-textbox) – Khalil Khalaf Aug 24 '16 at 12:58
  • 1
    @FirstStep: As already noted in that answer's comments, that code has several errors in it. Additionally it uses WinForms libraries; something I'd like to avoid unless there's no other way. – dotNET Aug 24 '16 at 13:13
  • To me, that's a reasonable distinction between the two questions. I don't think this needs to be closed as a duplicate. –  Aug 24 '16 at 13:19
  • I would expect MS sealed the `Cursor` class as a security concern. I could imagine it'd be much easier to mouselog or even take control of the mouse if you could inherit from `Cursor`. Not exactly helpful, but food for thought. – Mike Eason Aug 25 '16 at 07:25
  • @MikeEason: Not sure how that's possible. `Cursor` class doesn't control mouse position or any other mouse functionality for that matter. It just controls the visual appearance of the pointer. – dotNET Aug 25 '16 at 07:30

1 Answers1

6

Finally managed it within the bounds of WPF, without using WinForms or PInvokes. Instead of creating custom cursors (*.cur) on the fly or converting Visuals into cursors, I used MouseMove event of the parent control along with a WPF element (Path) as my cursor. Here's the way just in case anyone is interesed:

  1. Set the Cursor of your resize thumb (or whatever you're using as the border of your shape) to None, so that WPF doesn't display default arrow.
  2. Create your own cursor. Could be any FrameworkElement, but I have used Path for its easy manipulation to create any shape you want. Note that most of the properties I have set below are important.

    <Path x:Name="PART_EW" Data="M0,20 L25,0 25,15 75,15 75,0 100,20 75,40 75,25 25,25 25,40z" Fill="White" Stroke="Black" StrokeThickness="1" Visibility="Collapsed" Width="50" Height="20" Opacity=".7" Stretch="Fill" Panel.ZIndex="100001" HorizontalAlignment="Left" VerticalAlignment="Top" IsHitTestVisible="False" />

Add the following code in your resize thumb:

protected override void OnMouseEnter(MouseEventArgs e)
{
  base.OnMouseEnter(e);

  var Pos = e.GetPosition(this);
  PART_EW.Margin = new Thickness(
                       Pos.X - PART_EW.Width / 2, 
                       Pos.Y - PART_EW.Height / 2, 
                       -PART_EW.Width, 
                       -PART_EW.Height);
  PART_EW.Visibility = Visibility.Visible;
}

protected override void OnMouseLeave(MouseEventArgs e)
{
  base.OnMouseLeave(e);
  PART_EW.Visibility = Visibility.Collapsed;
}

protected override void OnMouseMove(MouseEventArgs e)
{
  base.OnMouseMove(e);

  var Pos = e.GetPosition(designerItem);
  PART_EW.Margin = new Thickness(
                       Pos.X - PART_EW.Width / 2, 
                       Pos.Y - PART_EW.Height / 2, 
                       -PART_EW.Width, 
                       -PART_EW.Height);
}

Note that I've not set RotateTransform of my Path anywhere in the code, since it is already part of the resize thumb and therefore acquires the angle of the parent control automatically.

Hope this helps people down the road.

dotNET
  • 33,414
  • 24
  • 162
  • 251
  • Deleted my comment.. Figured it out i can just use a RotateTransform on the Path to get the desired direction of the cursor. Only thing is that i also use a ScaleTransform on my Canvas, which also scales my cursor. Currently trying to apply a Inverse to make it look good. Thank your for the hint in the right direction. – bslein May 08 '18 at 13:27