How to create jewelry that does not scale using AdornedElement?

Simply put, I want to create some resize / rescale attributes to attach to the FrameworkElement that will allow the user to resize the element if they usually use covers, and allow them to resize the element (not necessarily evenly) if they use the lower right adorner and hold the SHIFT button down time of it.

I tried various ways to achieve this, but I always end up with the decorators themselves being scaled, so they end up in huge or massive borders. Since then, I started using positions relative to the window to place them, and ignored the RenderTransform applied to the AdornedElement, however I get very unusual behavior.

First, when I scale the item more (about) 2x, the zoom behavior breaks and starts jumping around the place.

Obviously, this behavior is easier to see than to describe, so I attached a sample solution (VS 2010) that demonstrates the problem and the code that causes it.

VS 2010 Solution Example

If anyone can give me any pointers in the right direction, please feel free to tell me that I'm doing it all wrong! lol.

In addition, to keep in mind that this adorner will also have to display correctly if the main decorated element is rotated, which it will not currently be.

Update: just to make NVM happy, here is a solution that does it in its own way: NVM way

+4
source share
2 answers

Assuming you have Thumbs inside an adorner to drag / rotate, etc., you will first want to stop them from scaling so that you do this in an override of GetDesiredTransform. Apply the return scale that you applied to the framework element. This makes your thumbs not scalable when resized.

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); } 

The next problem will be to create the thumbs so that they are in the right places after scaling / rotation, etc. Since you changed the render transformation for the thumb, you also need to manually organize it using ArrangeOverride.

To do this, save a list of all your thumbs and what positions they should be. If you deal only with square elements, your work is done halfway because you only need to deal with corners and sides.

 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; } 

If you do not know how to arrange, see this project project article .

If you still can't get it to work, show us the appropriate code (rather than a visual studio solution) that is likely to cause problems and someone will help you, I'm sure.

EDIT

Simplify your code first to understand your problem.

  • Remove all thumbs and event handlers except the btmRight thumb.
  • Add a DragCompleted event to btmRight Thumb. (Remove the drag delta)

Essentially, the essence of your problem code comes down to a commented line:

 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); } 

Now itโ€™s easy to understand the problem. This piece of code works great when dragging and resizing for the first time. This is because adornedElement.Width and adornedElement.Height are true when you drag it for the first time until scale transforms are applied. Once your drag and drop is complete, you assume that now the width and height will be the new width and height. This is not true! You see that this is just a transformation of the visualization, it does not change the width or height of the element. It just makes it bigger.

So what you need to do, first apply the existing scale transformation to the width and height, getting the visualized width and height. Then calculate the scale transform using these new values โ€‹โ€‹and add the transform to the group. Then you get what you want.

You will most likely have other problems when you do this in DragDelta. But in this case, you should ask a more specific question with only a small amount of relevant code , and you will get an answer from someone in a few minutes, I'm sure.

+6
source

Siyfion, the phenomenon that you see is real. The reason is that you do not compensate for the same scaling when handling Adorner drag and drop. In addition to the NVM answer, make sure you also have the following:

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

where you get the current display scale the same way. With these corrected values, the jumps around will stop. Jumping is actually a double drawing, first the system automatically using the wrong scaling, and secondly, using the resized, correct sizes provided by you. It appears at all levels of the scale, but only becomes apparent when scaling begins to increase.

+1
source

Source: https://habr.com/ru/post/1401037/


All Articles