Вращайтесь графический к мыши в WPF (как аналоговый набор)

$this->redirect('input/new/year/' . $year . '/month/' . $month);
7
задан Adam Harte 7 June 2009 в 22:45
поделиться

2 ответа

Я не встречал подобных элементов управления (хотя прошло некоторое время с тех пор, как я рассмотрел все элементы управления, предлагаемые поставщиками элементов управления WPF), но создать его относительно просто.

Все, что вам нужно сделать, это создать настраиваемый элемент управления, содержащий изображение (или рисунок XAML), который вы можете вращать, чтобы следовать за мышью. Затем привяжите RotateTransform к DependencyProperty 'Angle' в вашем настраиваемом элементе управления, чтобы при обновлении 'angle' изображение / рисунок вращались в соответствии с ним:

<UserControl x:Class="VolumeControlLibrary.VolumeControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:VolumeControlLibrary"
             Height="60" Width="60">
    <Image Source="/VolumeControl;component/knob.png" RenderTransformOrigin="0.5,0.5" >
        <Image.RenderTransform>
            <RotateTransform Angle="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:VolumeControl}}, Path=Angle}"/>
        </Image.RenderTransform>
    </Image>
</UserControl>

Установка RenderTransformOrigin на «0,5, 0,5» гарантирует, что элемент управления вращается вокруг своего центр, а не вращение вокруг левого верхнего угла; нам также придется компенсировать это при вычислении угла.

В коде файла для вашего элемента управления, добавить обработчики для мыши и Angle DependencyProperty:

public partial class VolumeControl : UserControl
{
    // Using a DependencyProperty backing store for Angle.
    public static readonly DependencyProperty AngleProperty =
        DependencyProperty.Register("Angle", typeof(double), typeof(VolumeControl), new UIPropertyMetadata(0.0));

    public double Angle
    {
        get { return (double)GetValue(AngleProperty); }
        set { SetValue(AngleProperty, value); }
    }

    public VolumeControl()
    {
        InitializeComponent();
        this.MouseLeftButtonDown += new MouseButtonEventHandler(OnMouseLeftButtonDown);
        this.MouseUp += new MouseButtonEventHandler(OnMouseUp);
        this.MouseMove += new MouseEventHandler(OnMouseMove);
    }

    private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        Mouse.Capture(this);
    }

    private void OnMouseUp(object sender, MouseButtonEventArgs e)
    {
        Mouse.Capture(null);
    }

    private void OnMouseMove(object sender, MouseEventArgs e)
    {
        if (Mouse.Captured == this)
        {
            // Get the current mouse position relative to the volume control
            Point currentLocation = Mouse.GetPosition(this);

            // We want to rotate around the center of the knob, not the top corner
            Point knobCenter = new Point(this.ActualHeight / 2, this.ActualWidth / 2);

            // Calculate an angle
            double radians = Math.Atan((currentLocation.Y - knobCenter.Y) / 
                                       (currentLocation.X - knobCenter.X));
            this.Angle = radians * 180 / Math.PI;

            // Apply a 180 degree shift when X is negative so that we can rotate
            // all of the way around
            if (currentLocation.X - knobCenter.X < 0)
            {
                this.Angle += 180;
            }
        }
    }
}

Захват мыши гарантирует, что ваш элемент управления будет продолжать получать обновления мыши, даже когда пользователь отводит курсор от элемента управления (пока он не отпустит щелчок), а также путем получения позиции мыши относительно текущего элемента (элемента управления), ваши вычисления всегда должны быть одинаковыми, независимо от того, где элемент управления фактически отображается на экране.

В этом примере, когда мышь перемещается, мы вычисляем угол между ним и центром элемента управления, а затем установите для этого угла значение Angle DependencyProperty, которое мы создали. Поскольку изображение, которое мы отображаем, привязано к этому свойству угла, WPF автоматически применяет новое значение, что приводит к вращению ручки в сочетании с перемещением мыши.

Использовать элемент управления в вашем решении легко; просто добавь:

<local:VolumeControl />

Вы должны привязаться к свойству Angle в VolumeControl, если хотите привязать значение регулятора к чему-то в вашем приложении; это значение в настоящее время выражено в градусах, но можно добавить дополнительное свойство для преобразования угла в градусы в значение, которое имеет смысл для вас (скажем, значение от 0 до 10).

19
ответ дан 6 December 2019 в 08:17
поделиться

Чтобы добавить к этому сообщению, угол между точкой мыши и точкой объекта рассчитывается следующим образом:

dot = currentLocation.X * objectPosition.X + currentLocation.Y * objectPosition.Y;
angle = Math.Acos(dot);
3
ответ дан 6 December 2019 в 08:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: