Как создавать украшения, которые не масштабируются с AdornedElement? - PullRequest
4 голосов
/ 12 марта 2012

Проще говоря, я хочу создать некоторые средства изменения размера / масштаба для присоединения к FrameworkElement, которые позволят пользователю изменять размер элемента, если они обычно используют средства украшения, и позволят им изменять масштаб элемента (не обязательно равномерно), если онииспользуйте правую нижнюю панель и удерживайте кнопку SHIFT при этом.

Я пробовал разные способы достижения этой цели, но я всегда заканчиваю тем, что сами украшатели масштабируются, так что они заканчиваются огромными, илис массивными границами.С тех пор я начал использовать позиции относительно окна для их позиционирования и игнорировал RenderTransform, примененный к AdornedElement, однако я получаю очень необычное поведение.

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

Очевидно, что это поведение легче увидеть, чем описать, поэтому я и приложил образецрешение (VS 2010), которое демонстрирует проблему и код, который ее вызывает.

Пример решения VS 2010

Если кто-то может дать мне какие-либо указатели в правильном направлении,пожалуйста, не стесняйтесь сказать мне, что я все делаю неправильно!lol.

Кроме того, чтобы иметь в виду, что этот украшатель в конечном итоге также должен будет отображаться правильно, если базовый украшенный элемент повернут, что в настоящее время не будет.

Обновление: просто сохранитьNVM доволен, вот решение, которое делает это по-своему: NVM's way

Ответы [ 2 ]

6 голосов
/ 13 марта 2012

Предполагая, что внутри перетаскивания / вращения и т. Д. У вас есть большие пальцы, вы сначала захотите остановить их масштабирование, чтобы сделать это в переопределении GetDesiredTransform. Примените обратную шкалу, примененную к элементу каркаса. Это приводит к тому, что ваши пальцы не масштабируются при изменении размера.

public override GeneralTransform GetDesiredTransform(GeneralTransform transform)
{
    double scaleFactor = GetCurrentScaleFactor(this._parent);

    if (this._visualChildren != null)
    {
        foreach (var thumb in this._visualChildren.OfType<Thumb>())
        {
            thumb.RenderTransform 
                = new ScaleTransform(1 / scaleFactor , 1 / scaleFactor );
            thumb.RenderTransformOrigin = new Point(0.5, 0.5);
        }
    }

    return base.GetDesiredTransform(transform);
}

Следующая проблема будет в том, чтобы расположить большие пальцы так, чтобы они находились в правильных местах после масштабирования / вращения и т. Д. Поскольку вы изменили преобразование рендеринга для большого пальца, теперь вы должны также вручную упорядочить его с помощью ArrangeOverride.

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

protected override Size ArrangeOverride(Size finalSize)
{
    var adornedElement = this.AdornedElement as FrameworkElement;

    // Use the width/height etc of adorned element to arrange the thumbs here
    // Its been a long time so either its width/height or actualwidth/actualheight
    // you will need to use.
    this._leftTopThumb.Arrange(Get the Rect To arrange here);  
    this._rightTopThumb.Arrange(Get the Rect To arrange here); 
    // etc

    return finalSize;
}

Если вы не знаете, как выполнять аранжировку См. Эту кодовую статью проекта.

Если вы все еще не можете заставить его работать, покажите нам соответствующий код (не решение Visual Studio), который может вызвать проблемы, и я уверен, что кто-то вам поможет.

EDIT

Сначала упростите ваш код, чтобы понять вашу проблему.

  1. Удалите все превью и обработчики событий, кроме большого пальца btmRight.
  2. Добавление события DragCompleted в большой палец btmRight. (Удалить дельта-перетаскивание)

По сути, суть вашего кода проблемы сводится к закомментированной строке:

void _btmRight_DragCompleted(object sender, DragCompletedEventArgs e)
{
    var adornedElement = AdornedElement as FrameworkElement;
    var hitThumb = sender as Thumb;
    if (adornedElement == null || hitThumb == null) return;

    var transformGroup = new TransformGroup();
    transformGroup.Children.Add(adornedElement.RenderTransform);

    //---- This is the problem line
    transformGroup.Children.Add(new ScaleTransform(1 + e.HorizontalChange / adornedElement.Width, 1 + e.VerticalChange / adornedElement.Height));
    //-------------------------------

    adornedElement.RenderTransform = new MatrixTransform(transformGroup.Value);
    }

Теперь легко разобраться в проблеме. Этот фрагмент кода отлично работает при первом перетаскивании и изменении размера. Это потому, что adornedElement.Width и adornedElement.Height верны, когда вы перетаскиваете его в первый раз, поскольку преобразования масштаба еще не были применены. Как только ваше перетаскивание завершено, вы предполагаете, что ширина и высота теперь будут новыми шириной и высотой. Это не так! Вы видите, что это просто преобразование рендера, оно не меняет ширину или высоту элемента. Это просто делает его больше.

Итак, что вам нужно сделать, это сначала применить существующее преобразование масштаба к ширине и высоте, чтобы получить визуализированную ширину и высоту. Затем вычислите масштабное преобразование, используя эти новые значения и добавьте в группу преобразований. Тогда вы получите то, что хотите.

Скорее всего, у вас все еще будут другие проблемы при выполнении этого в DragDelta. Но в этом случае вам следует задать более конкретный вопрос только с небольшим количеством соответствующего кода , и я уверен, что вы получите ответ от кого-то через несколько минут.

1 голос
/ 11 мая 2014

Сийфион, явление, которое вы видите, реально.Причина в том, что вы не компенсируете такое же масштабирование при обработке перетаскивания.В дополнение к ответу NVM, убедитесь, что у вас также есть:

double deltaX = args.HorizontalChange / CurrentDisplayScaleX;
double deltaY = args.VerticalChange / CurrentDisplayScaleX;

, где вы получаете текущую шкалу отображения таким же образом.С этими исправленными значениями прыжки вокруг прекратятся.Прыжки - это двойное рисование, сначала автоматически, используя неправильное масштабирование, во-вторых, используя измененные правильные размеры, предоставленные вами.Он появляется на всех уровнях шкалы, но становится очевидным, когда масштаб начинает увеличиваться.

...