WPF:应用RenderTransform,使GetPosition相对于中心,而不是左上角

时间:2011-03-07 22:13:47

标签: wpf-controls

我试图在A处拖动圆圈,使其相对于隐藏的中心元素B生成一个角度。

我正在使用MouseEventArgs.GetPosition(IInputElement relativeTo),所以:

Point p = args.GetPosition(B)

尽管在B上设置了RenderTransformOrigin 0.5,0.5,但我得到的是相对于B左上角的点,而不是它的中心。

我知道我可以手动计算正确的偏移量:Easiest way to get the angle of mouse position in WPF relative to the center of a circle

enter image description here

1 个答案:

答案 0 :(得分:3)

RenderTransformOrigin指定在B上应用的任何RenderTransform的相对来源。设置它本身不会改变B的位置,因此它也不会影响e.GetPosition(B)

人类语言中的

e.GetPosition(B)是“给我在B的坐标空间中的鼠标位置。无论你如何改变这个坐标空间(通过应用渲染变换),相对来说,B的中心将远离在它的中间,它将取决于它的大小,所以你需要计算它的中心。

同样,在计算角度时,您需要确保使用同一个坐标空间。此代码会在A上轮换Centre,无论它们的位置如何:

Point? dragStart;
    Point centrePoint;

    private void A_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        var handle = sender as FrameworkElement;
        var parent = handle.Parent as FrameworkElement;

        dragStart = e.GetPosition(parent);

        var rotateCentre = Centre.TransformToVisual(A).Transform(new Point(Centre.ActualWidth / 2, Centre.ActualHeight / 2));
        A.RenderTransform = new RotateTransform { CenterX = rotateCentre.X, CenterY = rotateCentre.Y };

        centrePoint = Centre.TransformToVisual(handle.Parent as FrameworkElement).Transform(new Point(Centre.ActualWidth / 2, Centre.ActualHeight / 2));
        handle.CaptureMouse();
    }

    private void A_MouseMove(object sender, MouseEventArgs e)
    {
        if (dragStart != null)
        {
            var current = e.GetPosition((sender as FrameworkElement).Parent as FrameworkElement);

            var angle = RadiansToDegrees(AngleAtoB(dragStart.Value, current, centrePoint));

            (A.RenderTransform as RotateTransform).Angle = angle;
        }
    }

    private void A_LostMouseCapture(object sender, MouseEventArgs e)
    {
        dragStart = null;
    }

    private void A_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        (sender as FrameworkElement).ReleaseMouseCapture();
    }

    internal static double AngleWithHorizontal(Point point, Point origin)
    {
        return Math.Atan2(point.Y - origin.Y, point.X - origin.X);
    }

    internal static double AngleAtoB(Point a, Point b, Point origin)
    {
        return AngleWithHorizontal(b, origin) - AngleWithHorizontal(a, origin);
    }

    private const double Const180OverPi = 180 / Math.PI;

    internal static double RadiansToDegrees(double angleInDegrees)
    {
        return angleInDegrees * Const180OverPi;
    }