1 <ControlTemplate x:Key="reSizeThumb" TargetType="{x:Type Thumb}"> 2 <Border Background="{DynamicResource BlueBrush}"> 3 </Border> 4 </ControlTemplate> 5 6 <ControlTemplate x:Key="moveThumb" TargetType="{x:Type Thumb}"> 7 <Grid x:Name="bg"> 8 <Grid.Background> 9 <RadialGradientBrush> 10 <GradientStop Color="#00000000" Offset="1"/> 11 <GradientStop Color="#50000000" Offset="1"/> 12 </RadialGradientBrush> 13 </Grid.Background> 14 </Grid> 15 </ControlTemplate> 16 17 <Style TargetType="{x:Type local:CropingImgEx}"> 18 <Setter Property="Template"> 19 <Setter.Value> 20 <ControlTemplate TargetType="{x:Type local:CropingImgEx}"> 21 <Border Background="{TemplateBinding Background}" 22 BorderBrush="{TemplateBinding BorderBrush}" 23 BorderThickness="{TemplateBinding BorderThickness}"> 24 <Grid> 25 <Image x:Name="imgSource" Source="{TemplateBinding Source}" Stretch="Uniform"/> 26 <Canvas x:Name="canvas"> 27 28 <Rectangle x:Name="topRec" Fill="{TemplateBinding MarkColor}" Canvas.Top="0" Width="{TemplateBinding Width}"/> 29 <Rectangle x:Name="leftRec" Fill="{TemplateBinding MarkColor}" Canvas.Left="0"/> 30 <Rectangle x:Name="bottomRec" Fill="{TemplateBinding MarkColor}" Canvas.Bottom="0" Width="{TemplateBinding Width}"/> 31 <Rectangle x:Name="rightRec" Fill="{TemplateBinding MarkColor}" Canvas.Right="0"/> 32 <Border x:Name="drogBorder" 33 Width="{TemplateBinding DragControlLength}" Height="{TemplateBinding DragControlLength}"> 34 <Grid UseLayoutRounding="True" SnapsToDevicePixels="True" Cursor="SizeAll" > 35 <Grid.Background> 36 <RadialGradientBrush> 37 <GradientStop Color="#00000000" Offset="1"/> 38 <GradientStop Color="#00000000" Offset="1"/> 39 </RadialGradientBrush> 40 </Grid.Background> 41 <Ellipse Stroke="{DynamicResource BlueBrush}" StrokeThickness="1" StrokeDashArray="4,4" /> 42 <Thumb x:Name="moveThumb" Width="{TemplateBinding DragControlLength}" Height="{TemplateBinding DragControlLength}" Template="{StaticResource moveThumb}"/> 43 <Thumb Height="5" Width="5" x:Name="thumbTopLeft" Margin="-5" Template="{StaticResource reSizeThumb}" HorizontalAlignment="Left" VerticalAlignment="Top" Cursor="SizeNWSE"/> 44 <Thumb Height="5" Width="5" x:Name="thumbTopRight" Margin="-5" Template="{StaticResource reSizeThumb}" HorizontalAlignment="Right" VerticalAlignment="Top" Cursor="SizeNESW"/> 45 <Thumb Height="5" Width="5" x:Name="thumbBottomLeft" Margin="-5" Template="{StaticResource reSizeThumb}" HorizontalAlignment="Left" VerticalAlignment="Bottom" Cursor="SizeNESW"/> 46 <Thumb Height="5" Width="5" x:Name="thumbBottomRight" Margin="-5" Template="{StaticResource reSizeThumb}" HorizontalAlignment="Right" VerticalAlignment="Bottom" Cursor="SizeNWSE"/> 47 48 49 </Grid> 50 </Border> 51 </Canvas> 52 53 </Grid> 54 </Border> 55 </ControlTemplate> 56 </Setter.Value> 57 </Setter> 58 </Style>
上面是 CropingImgEx 的默认样式 里面的5个Thumb主要用于拖动和装饰拖动的边框, 直接使用CropingSource 来获取BitmapSource 代码写的 比较渣 后期有待优化 附一张效果图
public class CropingImgEx : Control { static CropingImgEx() { DefaultStyleKeyProperty.OverrideMetadata(typeof(CropingImgEx), new FrameworkPropertyMetadata(typeof(CropingImgEx))); using (System.Drawing.Graphics graphics = System.Drawing.Graphics.FromHwnd(IntPtr.Zero)) { s_dpiX = graphics.DpiX; s_dpiY = graphics.DpiY; } } public CropingImgEx() { this.Unloaded += CropingImgEx_Unloaded; } public double DragControlLength { get { return (double)GetValue(DragControlLengthProperty); } set { SetValue(DragControlLengthProperty, value); } } public static readonly DependencyProperty DragControlLengthProperty = DependencyProperty.Register("DragControlLength", typeof(double), typeof(CropingImgEx), new PropertyMetadata(null)); public double MinControlLength { get { return (double)GetValue(MinControlLengthProperty); } set { SetValue(MinControlLengthProperty, value); } } // Using a DependencyProperty as the backing store for MinControlLength. This enables animation, styling, binding, etc... public static readonly DependencyProperty MinControlLengthProperty = DependencyProperty.Register("MinControlLength", typeof(double), typeof(CropingImgEx), new PropertyMetadata(null)); public Brush MarkColor { get { return (Brush)GetValue(MarkColorProperty); } set { SetValue(MarkColorProperty, value); } } // Using a DependencyProperty as the backing store for MarkColor. This enables animation, styling, binding, etc... public static readonly DependencyProperty MarkColorProperty = DependencyProperty.Register("MarkColor", typeof(Brush), typeof(CropingImgEx), new PropertyMetadata(null)); public BitmapSource CropingSource { get { return (BitmapSource)GetValue(CropingSourceProperty); } set { SetValue(CropingSourceProperty, value); } } // Using a DependencyProperty as the backing store for CropingSource. This enables animation, styling, binding, etc... public static readonly DependencyProperty CropingSourceProperty = DependencyProperty.Register("CropingSource", typeof(BitmapSource), typeof(CropingImgEx), new PropertyMetadata(null)); public BitmapSource Source { get { return (BitmapSource)GetValue(SourceProperty); } set { SetValue(SourceProperty, value); } } public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(BitmapSource), typeof(CropingImgEx), new PropertyMetadata(new PropertyChangedCallback( OnSourceChanged))); public static void OnSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { CropingImgEx img = sender as CropingImgEx; if (e.NewValue != null) { BitmapSource source = e.NewValue as BitmapSource; if (img.imgSource != null) { Size targetSize = img.Preview(source.PixelWidth, source.PixelHeight, 300, 300); img.Width = targetSize.Width; img.Height = targetSize.Height; img.DragControlLength = Math.Min(targetSize.Width, targetSize.Height); Canvas.SetTop(img.dragBorder, 0); Canvas.SetLeft(img.dragBorder, 0); img.SetMark(0, 0); img.SetCropingSource(); } } } Size Preview(double sourceWidht,double sourceHeight, double maxWidth, double maxHeight) { scaleX = maxWidth / sourceWidht; scaleY = maxHeight / sourceHeight; Size result; if (scaleX < scaleY) { result = new Size(maxWidth, (int)(sourceHeight * scaleX)); } else if (scaleX > scaleY) { result = new Size((int)(sourceWidht * scaleY), maxHeight); } else { result = new Size(maxWidth, maxHeight); } return result; } private Thumb moveThumb; private Thumb thumbTopLeft; private Thumb thumbTopRight; private Thumb thumbBottomLeft; private Thumb thumbBottomRight; private FrameworkElement dragBorder; private Rectangle markTop; private Rectangle markLeft; private Rectangle markRight; private Rectangle markBottom; private Image imgSource; public override void OnApplyTemplate() { base.OnApplyTemplate(); moveThumb = GetTemplateChild("moveThumb") as Thumb; thumbTopLeft = GetTemplateChild("thumbTopLeft") as Thumb; thumbTopRight = GetTemplateChild("thumbTopRight") as Thumb; thumbBottomLeft = GetTemplateChild("thumbBottomLeft") as Thumb; thumbBottomRight = GetTemplateChild("thumbBottomRight") as Thumb; dragBorder = GetTemplateChild("drogBorder") as FrameworkElement; markTop = GetTemplateChild("topRec") as Rectangle; markLeft = GetTemplateChild("leftRec") as Rectangle; markRight = GetTemplateChild("rightRec") as Rectangle; markBottom = GetTemplateChild("bottomRec") as Rectangle; imgSource = GetTemplateChild("imgSource") as Image; Canvas.SetTop(dragBorder, (Width - DragControlLength) / 2); Canvas.SetLeft(dragBorder, (Height - DragControlLength) / 2); moveThumb.DragDelta += moveThumb_DragDelta; thumbTopLeft.DragDelta += thumbTopLeft_DragDelta; thumbTopRight.DragDelta += thumbTopRight_DragDelta; thumbBottomLeft.DragDelta += thumbBottomLeft_DragDelta; thumbBottomRight.DragDelta += thumbBottomRight_DragDelta; thumbTopLeft.DragCompleted += thumbBottomLeft_DragCompleted; thumbTopRight.DragCompleted += thumbBottomLeft_DragCompleted; thumbBottomLeft.DragCompleted += thumbBottomLeft_DragCompleted; thumbBottomRight.DragCompleted += thumbBottomLeft_DragCompleted; SetCropingSource(); SetMark((Width - DragControlLength) / 2, (Height - DragControlLength) / 2); } void CropingImgEx_Unloaded(object sender, RoutedEventArgs e) { moveThumb.DragDelta -= moveThumb_DragDelta; thumbTopLeft.DragDelta -= thumbTopLeft_DragDelta; thumbTopRight.DragDelta -= thumbTopRight_DragDelta; thumbBottomLeft.DragDelta -= thumbBottomLeft_DragDelta; thumbBottomRight.DragDelta -= thumbBottomRight_DragDelta; thumbBottomLeft.DragCompleted -= thumbBottomLeft_DragCompleted; thumbTopRight.DragCompleted -= thumbBottomLeft_DragCompleted; thumbBottomLeft.DragCompleted -= thumbBottomLeft_DragCompleted; thumbBottomRight.DragCompleted -= thumbBottomLeft_DragCompleted; } void thumbBottomLeft_DragCompleted(object sender, DragCompletedEventArgs e) { SetCropingSource(); } void thumbBottomRight_DragDelta(object sender, DragDeltaEventArgs e) { if (e.HorizontalChange == 0) { return; } double width = DragControlLength + e.HorizontalChange; double top = Canvas.GetTop(dragBorder); double left = Canvas.GetLeft(dragBorder); Console.WriteLine("Resize Left:" + Canvas.GetLeft(dragBorder) + "\tResize Top:" + Canvas.GetTop(dragBorder)); if (left + width > Width || width + top > Height || width <= MinControlLength) { return; } DragControlLength = width; SetMark(top, left); e.Handled = true; } void thumbBottomLeft_DragDelta(object sender, DragDeltaEventArgs e) { if (e.HorizontalChange == 0) { return; } double width = DragControlLength - e.HorizontalChange; double left = Canvas.GetLeft(dragBorder) + e.HorizontalChange; double top = Canvas.GetTop(dragBorder); Console.WriteLine("Resize Left:" + Canvas.GetLeft(dragBorder) + "\tResize Top:" + Canvas.GetTop(dragBorder)); if (left < 0 || width <= MinControlLength || top + width > Height) { return; } Canvas.SetLeft(dragBorder, left); DragControlLength = width; SetMark(top, left); e.Handled = true; } void thumbTopRight_DragDelta(object sender, DragDeltaEventArgs e) { if (e.HorizontalChange == 0) { return; } double width = DragControlLength + e.HorizontalChange; double top = Canvas.GetTop(dragBorder) - e.HorizontalChange; double left = Canvas.GetLeft(dragBorder); Console.WriteLine("Resize Left:" + Canvas.GetLeft(dragBorder) + "\tResize Top:" + Canvas.GetTop(dragBorder)); if (top < 0 || left + width >= Width || width < MinControlLength) { return; } Canvas.SetTop(dragBorder, top); DragControlLength = width; SetMark(top, left); e.Handled = true; } void thumbTopLeft_DragDelta(object sender, DragDeltaEventArgs e) { if (e.HorizontalChange == 0) { return; } double width = DragControlLength - e.HorizontalChange; double top = Canvas.GetTop(dragBorder) + e.HorizontalChange; double left = Canvas.GetLeft(dragBorder) + e.HorizontalChange; Console.WriteLine("Resize Left:" + Canvas.GetLeft(dragBorder) + "\tResize Top:" + Canvas.GetTop(dragBorder)); if (top < 0 || width <= MinControlLength || left < 0) { return; } Canvas.SetTop(dragBorder, top); Canvas.SetLeft(dragBorder, left); DragControlLength = width; SetMark(top, left); e.Handled = true; } void moveThumb_DragDelta(object sender, DragDeltaEventArgs e) { double top = Canvas.GetTop(dragBorder) + e.VerticalChange; double left = Canvas.GetLeft(dragBorder) + e.HorizontalChange; if (top <= 0) top = 0; if (top >= (Height - DragControlLength)) top = Height - DragControlLength; if (left <= 0) left = 0; if (left >= (Width - DragControlLength)) left = Width - DragControlLength; Canvas.SetTop(dragBorder, nTop); Canvas.SetLeft(dragBorder, nLeft); SetCropingSource(); SetMark(nTop, nLeft); Console.WriteLine("Move Left:" + Canvas.GetLeft(dragBorder) + "\tMove Top:" + Canvas.GetTop(dragBorder)); } private static float s_dpiX; private static float s_dpiY; private double scaleX; // 缩放比例 private double scaleY; // private Point UnitsToPx(double x, double y) { scaleX = Source.PixelWidth / this.Width; scaleY = Source.PixelHeight / this.Height; return new Point((int)(x * s_dpiX / 96), (int)(y * s_dpiY / 96)); } private void SetCropingSource() { Point point = UnitsToPx(Canvas.GetLeft(dragBorder), Canvas.GetTop(dragBorder)); int left = (int)(point.X * scaleX); int top = (int)(point.Y * scaleY); int width = (int)(dragBorder.Width * scaleX); int height = (int)(dragBorder.Height * scaleY); Int32Rect rect = new Int32Rect(left, top, width, height); CroppedBitmap bitImage = new CroppedBitmap(Source, rect); CropingSource = bitImage; } private void SetMark(double top, double left) { markTop.Height = top; double height = Height - top - DragControlLength; if (height < 0) { height = 0; } markBottom.Height = height; markLeft.Width = left; markLeft.Height = DragControlLength; Canvas.SetTop(markLeft, top); markRight.Width = Width - left - DragControlLength; markRight.Height = DragControlLength; Canvas.SetTop(markRight, top); } }