namespace AvalonApplication7
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
//Initialize the application by calling a method
//to apply adorners to all children of the respective
//Canvas.
private void StartUp(object sender, EventArgs args)
{
ApplyAdornersToCanvasChildren(mainCanvas);
}
//Iterates through the Canvas' children finding all of
//the FrameworkElements; it then applies a CustomResizeAdorner
//to each one.
void ApplyAdornersToCanvasChildren(Canvas canvas)
{
AdornerLayer al = AdornerDecorator.GetAdornerLayer(canvas);
foreach (FrameworkElement fxe in canvas.Children)
if (al.GetAdorners(fxe) == null)
al.Add(new CustomResizeAdorner(fxe));
}
}
public class CustomResizeAdorner : Adorner
{
//The visual elements used as the Adorners. The Thumb
//element is used because it takes care of handling the
//lower level mouse input.
Thumb topLeft, topRight, bottomLeft, bottomRight;
//Initialize the CustomResizeAdorner.
public CustomResizeAdorner(UIElement adornedElement) : base(adornedElement)
{
//Call a helper method to instantiate the Thumbs
//with a given Cursor.
BuildAdornerCorner(ref topLeft, Cursors.SizeNWSE);
BuildAdornerCorner(ref topRight, Cursors.SizeNESW);
BuildAdornerCorner(ref bottomLeft, Cursors.SizeNESW);
BuildAdornerCorner(ref bottomRight, Cursors.SizeNWSE);
//Add handlers for resizing on the bottom left and right.
//Leaving the handling of the other two corners as an exercise
//to the reader.
bottomLeft.DragDelta += new DragDeltaEventHandler(HandleBottomLeft);
bottomRight.DragDelta += new DragDeltaEventHandler(HandleBottomRight);
}
//Handle resize for the bottom right adorner widget.
void HandleBottomRight(object sender, DragDeltaEventArgs args)
{
FrameworkElement fxe = AdornedElement as FrameworkElement;
Thumb hitThumb = sender as Thumb;
if (fxe == null || hitThumb == null)
return;
EnforceSize(fxe);
//Change the size by the amount the user drags the mouse as
//long as it's larger than the width or height of an adorner, respectively.
fxe.Width = Math.Max(args.HorizontalChange + fxe.Width, hitThumb.DesiredSize.Width);
fxe.Height = Math.Max(args.VerticalChange + fxe.Height, hitThumb.DesiredSize.Height);
}
//Handle resize for the bottom left adorner widget.
void HandleBottomLeft(object sender, DragDeltaEventArgs args)
{
FrameworkElement fxe = AdornedElement as FrameworkElement;
Thumb hitThumb = sender as Thumb;
if (fxe == null || hitThumb == null)
return;
EnforceSize(fxe);
//Change the size by the amount the user drags the mouse as
//long as it's larger than the width or height of an adorner, respectively.
//Also, update the left position by the amount the user drags as long as
//it's not past the right edge minus the adorner widget width.
Canvas.SetLeft(fxe, Math.Min((double)Canvas.GetLeft(fxe) + args.HorizontalChange,(double)Canvas.GetLeft(fxe) + fxe.Width - hitThumb.DesiredSize.Width));
fxe.Width = Math.Max(fxe.Width - args.HorizontalChange, hitThumb.DesiredSize.Width);
fxe.Height = Math.Max(args.VerticalChange + fxe.Height, hitThumb.DesiredSize.Height);
}
//Arrange the Adorners.
protected override Size ArrangeOverride(Size finalSize)
{
//w & h are the width and height of the element
//that's being adorned. These will be used to place
//the Adorner at the corners. adornerWidth &
//adornerHeight are used for placement as well.
double w = AdornedElement.DesiredSize.Width;
double h = AdornedElement.DesiredSize.Height;
double adornerWidth = this.DesiredSize.Width;
double adornerHeight = this.DesiredSize.Height;
topLeft.Arrange(new Rect(-adornerWidth / 2, -adornerHeight / 2, adornerWidth, adornerHeight));
topRight.Arrange(new Rect(w - adornerWidth / 2, -adornerHeight / 2, adornerWidth, adornerHeight));
bottomLeft.Arrange(new Rect(-adornerWidth / 2, h - adornerHeight / 2, adornerWidth, adornerHeight));
bottomRight.Arrange(new Rect(w - adornerWidth / 2, h -adornerHeight / 2, adornerWidth, adornerHeight));
//Just using the size that the
//adorner layer was arranged at.
return finalSize;
}
//Helper code to instantiate the Thumbs, set the
//Cursor property and add the elements to the
//Visual tree.
void BuildAdornerCorner(ref Thumb cornerThumb, Cursor c)
{
if (cornerThumb != null) return;
cornerThumb = new Thumb();
cornerThumb.Cursor = c;
VisualOperations.GetChildren(this).Add(cornerThumb);
}
//This method ensures that the Widths and Heights
//are initialized. Sizing to content produces
//Width and Height values of Double.NaN. Because
//this Adorner explicitly resizes, the Width and Height
//need to be set first.
void EnforceSize(FrameworkElement fxe)
{
if (fxe.Width.Equals(Double.NaN))
fxe.Width = fxe.DesiredSize.Width;
if (fxe.Height.Equals(Double.NaN))
fxe.Height = fxe.DesiredSize.Height;
}
}
}