lecloneur lecloneur - 5 months ago 25
C# Question

How to get mouse position on part of CustomControl

In the making of a customcontrol, I'm trying to get the mouse position on a Canvas which is a container inside my custom control. Problem is, when I put my customcontrol in a testing app, just a grid in a window, what I get is always the mouse position on the window itself but not the mouse position on my customcontrol.

public class HueWheel : Control
static HueWheel()
DefaultStyleKeyProperty.OverrideMetadata(typeof(HueWheel), new FrameworkPropertyMetadata(typeof(HueWheel)));
private bool _isPressed = false;
//private Canvas _templateCanvas = null;
private Canvas _PART_FirstCanvas;
private Canvas _PART_SecondCanvas;
private Slider _PART_Slider;

public override void OnApplyTemplate()
_PART_FirstCanvas = (Canvas)GetTemplateChild("PART_FirstCanvas");
_PART_SecondCanvas = (Canvas)GetTemplateChild("PART_SecondCanvas");
_PART_Slider = (Slider)GetTemplateChild("PART_Slider");

protected override void OnMouseMove(MouseEventArgs e)
if (_isPressed)
const double RADIUS = 150;
Point newPos = e.GetPosition(_PART_SecondCanvas);
double angle = MyHelper.GetAngleR(newPos, RADIUS);
_PART_Slider.Value = (_PART_Slider.Maximum - _PART_Slider.Minimum) * angle / (2 * Math.PI);

protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
_isPressed = true;

protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
_isPressed = false;

This is the xaml contained in Generic.xaml

<Style TargetType="{x:Type local:HueWheel}">
<Setter Property="Template">
<ControlTemplate TargetType="{x:Type local:HueWheel}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<Slider x:Name="PART_Slider">
<Canvas x:Name="PART_FirstCanvas" Width="300" Height="300">
<Image Stretch="Fill" Source="Assets/HueCircle.PNG" Focusable="False" Height="300" Width="300" RenderTransformOrigin="0.5,0.5">
<RotateTransform Angle="270"/>
<Ellipse Fill="Transparent" Width="300" Height="300" Canvas.Left="0" Canvas.Top="0"/>
<Canvas x:Name="PART_SecondCanvas">
<Line Stroke="Transparent" StrokeThickness="5" X1="150" Y1="150" X2="150" Y2="0"/>
<Ellipse Fill="Black" Width="20" Height="20" Canvas.Left="140" Canvas.Top="30"/>
<RotateTransform CenterX="150" CenterY="150">
<MultiBinding Converter="{StaticResource ValueAngleConverter}">
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Value"/>
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Minimum"/>
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="Maximum"/>

Also, the mouse position is output only if mouse is on canvas, so it's kind of half working here... little confuse.

These are the two function I use for angle calculation :

public static double GetAngle(double value, double maximum, double minimum)
double current = (value / (maximum - minimum)) * 360;
if (current == 360)
current = 359.999;

return current;

public static double GetAngleR(Point pos, double radius)
Point center = new Point(radius, radius);
double xDiff = center.X - pos.X;
double yDiff = center.Y - pos.Y;
double r = Math.Sqrt(xDiff * xDiff + yDiff * yDiff);

double angle = Math.Acos((center.Y - pos.Y) / r);

if (pos.X < radius)
angle = 2 * Math.PI - angle;

if (Double.IsNaN(angle))
return 0.0;
return angle;

Any hint ?

Thank you


In your code

Point ControlPos = e.GetPosition (this);
Point WindowPos = e.GetPosition( Application.Current.MainWindow );

Will give you - coordinates in the Control and Window coordinates.