Win10 for Phone 裁剪控件
<Page.BottomAppBar> <CommandBar x:Name="appBar"> <AppBarButton Label="裁切" Icon="Crop" Click="AppBarButton_Crop_Click"> </AppBarButton> <AppBarButton Label="完成" Icon="Accept" Click="AppBarButton_Accept_Click"> </AppBarButton> </CommandBar> </Page.BottomAppBar> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Image Name="CroppedImage" Grid.Row="1" CacheMode="BitmapCache" ManipulationMode="All" PointerPressed="CroppedImage_PointerPressed" PointerReleased="CroppedImage_PointerReleased" PointerMoved="CroppedImage_PointerMoved"> <!--<Image.Clip> <RectangleGeometry x:Name="ClipRect"/> </Image.Clip>--> </Image> <Canvas Name="CropCanvas" Grid.RowSpan="2"> <Rectangle Name="LeftBack" HorizontalAlignment="Left" VerticalAlignment="Top" Fill="#99000000" IsHitTestVisible="False"/> <Rectangle Name="TopBack" HorizontalAlignment="Left" VerticalAlignment="Top" Fill="#99000000" IsHitTestVisible="False"/> <Rectangle Name="RightBack" HorizontalAlignment="Left" VerticalAlignment="Top" Fill="#99000000" IsHitTestVisible="False"/> <Rectangle Name="BottomBack" HorizontalAlignment="Left" VerticalAlignment="Top" Fill="#99000000" IsHitTestVisible="False"/> <TextBlock Name="SizeLabel" Width="72" TextAlignment="Right" FontSize="14" Foreground="Gray" IsHitTestVisible="False" FontFamily="{StaticResource PhoneFontFamilyNormal}"/> <Rectangle Name="TL" Height="24" HorizontalAlignment="Left" VerticalAlignment="Top" Width="24" StrokeThickness="1" Stroke="Transparent" IsHitTestVisible="False" Fill="Transparent" Canvas.Left="{x:Bind PinTL.Left,Mode=OneWay}" Canvas.Top="{x:Bind PinTL.Top,Mode=OneWay}"/> <Rectangle Name="TR" Height="24" HorizontalAlignment="Left" VerticalAlignment="Top" Width="24" StrokeThickness="1" Stroke="Transparent" IsHitTestVisible="False" Fill="Transparent" Canvas.Left="{x:Bind PinTR.Left,Mode=OneWay}" Canvas.Top="{x:Bind PinTR.Top,Mode=OneWay}"/> <Rectangle Name="BL" Height="24" HorizontalAlignment="Left" VerticalAlignment="Top" Width="24" StrokeThickness="1" Stroke="Transparent" IsHitTestVisible="False" Fill="Transparent" Canvas.Left="{x:Bind PinBL.Left,Mode=OneWay}" Canvas.Top="{x:Bind PinBL.Top,Mode=OneWay}"/> <Rectangle Name="BR" Height="24" HorizontalAlignment="Left" VerticalAlignment="Top" Width="24" StrokeThickness="1" Stroke="Transparent" IsHitTestVisible="False" Fill="Transparent" Canvas.Left="{x:Bind PinBR.Left,Mode=OneWay}" Canvas.Top="{x:Bind PinBR.Top,Mode=OneWay}"/> </Canvas> </Grid>
#region 常量 private Rectangle activePin; private const double doublePinSize = 48; private const double halfPinSize = 12; private bool isNew; private double minHeight; private double minWidth; private bool moveRect; private Point offset; private PinRect PinBL; private PinRect PinBR; private const double pinSize = 24; private PinRect PinTL; private PinRect PinTR; private int realHeight; private int realWidth; private double scale; private int startX; private int startY; private Point tapDiff; #endregion BitmapImage mSourceBitmap; public PhotoChooserPage() { this.InitializeComponent(); SizeChangedEventHandler sizeChangedEventHandler = null; this.tapDiff = new Point(0, 0); this.scale = 1; this.minWidth = 1; this.minHeight = 1; this.PinTL = new PinRect(); this.PinBL = new PinRect(); this.PinTR = new PinRect(); this.PinBR = new PinRect(); this.TL.DataContext = this.PinTL; this.BL.DataContext = this.PinBL; this.TR.DataContext = this.PinTR; this.BR.DataContext = this.PinBR; Image croppedImage = this.CroppedImage; if (sizeChangedEventHandler == null) { sizeChangedEventHandler = (object s, SizeChangedEventArgs e) => this.InitImage(); } croppedImage.SizeChanged += sizeChangedEventHandler; } private void InitImage() { if (this.isNew) { this.isNew = false; GeneralTransform visual = this.CroppedImage.TransformToVisual(Window.Current.Content); this.offset = visual.TransformPoint(new Point(0, 0)); Size renderSize = this.CroppedImage.RenderSize; this.scale = renderSize.Width / (double)mSourceBitmap.PixelWidth; double num = this.scale * 100; ForUserInit(); } } void ForUserInit() { this.minWidth = 100; this.minHeight = 100; Size renderSize = this.CroppedImage.RenderSize; double left = 0; double right = 0; if (renderSize.Width > 100) left = (renderSize.Width - 100) / 2; if (renderSize.Height > 100) right = (renderSize.Height - 100) / 2; double x = this.offset.X + left; double y = this.offset.Y + right; //左上角 this.PinTL.RealLeft = x; this.PinTL.RealTop = y; //左下角 this.PinBL.RealLeft = x; this.PinBL.RealTop = y + this.minHeight - 24; //右上角 this.PinTR.RealLeft = x + this.minWidth - 24; this.PinTR.RealTop = y; //右下角 this.PinBR.RealLeft = x + this.minWidth - 24; this.PinBR.RealTop = y + this.minHeight - 24; this.CroppedImage_PointerMoved(null, null); } protected override void OnNavigatedTo(NavigationEventArgs e) { if (e.NavigationMode == NavigationMode.New) { // 如果用户选择了图片,则显示在屏幕上 mSourceBitmap = e.Parameter as BitmapImage; //CroppedImage CroppedImage.Source = mSourceBitmap; isNew = true; } } private void CroppedImage_PointerPressed(object sender, PointerRoutedEventArgs e) { Point position = e.GetCurrentPoint(this.CroppedImage).Position; this.activePin = null; this.moveRect = false; if (this.IsRectTapped(position.X + this.offset.X, position.Y + this.offset.Y)) { this.moveRect = true; } if (this.IsPinTapped(this.PinTL, position.X + this.offset.X, position.Y + this.offset.Y)) { this.activePin = this.TL; } if (this.IsPinTapped(this.PinTR, position.X + this.offset.X, position.Y + this.offset.Y)) { this.activePin = this.TR; } if (this.IsPinTapped(this.PinBL, position.X + this.offset.X, position.Y + this.offset.Y)) { this.activePin = this.BL; } if (this.IsPinTapped(this.PinBR, position.X + this.offset.X, position.Y + this.offset.Y)) { this.activePin = this.BR; } } private void CroppedImage_PointerReleased(object sender, PointerRoutedEventArgs e) { this.moveRect = false; this.activePin = null; } private void CroppedImage_PointerMoved(object sender, PointerRoutedEventArgs e) { Point position; if (e != null) { position = e.GetCurrentPoint(this.CroppedImage).Position; } else { Point point = new Point(); position = point; } Point point1 = position; double x = point1.X + this.offset.X + this.tapDiff.X; double y = point1.Y + this.offset.Y + this.tapDiff.Y; double realLeft = this.PinBR.RealLeft - this.PinTL.RealLeft; double realTop = this.PinBR.RealTop - this.PinTL.RealTop; if (this.activePin == null) { if (this.moveRect) { if (x < this.offset.X) { x = this.offset.X; } Size renderSize = this.CroppedImage.RenderSize; if (x > this.offset.X + renderSize.Width - realLeft - 24) { Size size = this.CroppedImage.RenderSize; x = this.offset.X + size.Width - realLeft - 24; } if (y < this.offset.Y) { y = this.offset.Y; } Size renderSize1 = this.CroppedImage.RenderSize; if (y > this.offset.Y + renderSize1.Height - realTop - 24) { Size size1 = this.CroppedImage.RenderSize; y = this.offset.Y + size1.Height - realTop - 24; } this.PinTL.RealLeft = x; this.PinTL.RealTop = y; this.PinBL.RealLeft = x; this.PinBL.RealTop = y + realTop; this.PinBR.RealLeft = x + realLeft; this.PinBR.RealTop = y + realTop; this.PinTR.RealLeft = x + realLeft; this.PinTR.RealTop = y; } } else this.MoveInRatio(x, 1); Point imageSize = this.GetImageSize(); this.LeftBack.SetValue(Canvas.LeftProperty, this.offset.X); this.LeftBack.SetValue(Canvas.TopProperty, this.offset.Y); this.LeftBack.Height = Math.Max(0, Math.Ceiling(imageSize.Y)); this.LeftBack.Width = Math.Max(0, (double)this.PinTL.Left - this.offset.X); this.RightBack.SetValue(Canvas.LeftProperty, (double)this.PinBR.Left + 24); this.RightBack.SetValue(Canvas.TopProperty, this.offset.Y); this.RightBack.Height = Math.Max(0, Math.Ceiling(imageSize.Y)); this.RightBack.Width = Math.Max(0, Math.Ceiling(imageSize.X) + this.offset.X - 24 - (double)this.PinBR.Left); this.TopBack.SetValue(Canvas.LeftProperty, (double)this.PinTL.Left); this.TopBack.SetValue(Canvas.TopProperty, this.offset.Y); this.TopBack.Height = Math.Max(0, (double)this.PinTL.Top - this.offset.Y); this.TopBack.Width = Math.Max(0, (double)(this.PinBR.Left - this.PinTL.Left) + 24); this.BottomBack.SetValue(Canvas.LeftProperty, (double)this.PinTL.Left); this.BottomBack.SetValue(Canvas.TopProperty, (double)this.PinBR.Top + 24); this.BottomBack.Height = Math.Max(0, Math.Ceiling(imageSize.Y) + this.offset.Y - 24 - (double)this.PinBR.Top); this.BottomBack.Width = Math.Max(0, (double)(this.PinBR.Left - this.PinTL.Left) + 24); realLeft = this.PinBR.RealLeft - this.PinTL.RealLeft; realTop = this.PinBR.RealTop - this.PinTL.RealTop; this.startX = (int)Math.Round((this.PinTL.RealLeft - this.offset.X) / this.scale); this.startY = (int)Math.Round((this.PinTL.RealTop - this.offset.Y) / this.scale); this.realWidth = (int)Math.Round((realLeft + 24) / this.scale); this.realHeight = (int)Math.Round((realTop + 24) / this.scale); } private Point GetImageSize() { Size renderSize = this.CroppedImage.RenderSize; if (renderSize.Height == 0) { Size size = this.CroppedImage.RenderSize; if (size.Width == 0) { return new Point(this.CroppedImage.ActualWidth, this.CroppedImage.ActualHeight); } } Size renderSize1 = this.CroppedImage.RenderSize; Size size1 = this.CroppedImage.RenderSize; return new Point(renderSize1.Width, size1.Height); } private bool IsPinTapped(PinRect pin, double left, double top) { bool flag; if (left < pin.RealLeft - 12 || left > pin.RealLeft + 36 || top < pin.RealTop - 12) { flag = false; } else { flag = top <= pin.RealTop + 36; } bool flag1 = flag; if (flag1) { this.tapDiff = new Point(pin.RealLeft - left, pin.RealTop - top); } return flag1; } private bool IsRectTapped(double left, double top) { Rect rect = new Rect(this.PinTL.RealLeft, this.PinTL.RealTop, this.PinBR.RealLeft + 24, this.PinBR.RealTop + 24); bool flag = rect.Contains(new Point(left, top)); if (flag) { this.tapDiff = new Point(this.PinTL.RealLeft - left, this.PinTL.RealTop - top); } return flag; } private void MoveInRatio(double y, double rate) { if (this.activePin.Equals(this.BR)) { double x = y; double realLeft = (x + 24 - this.PinTL.RealLeft) / rate + this.PinTL.RealTop - 24; Size renderSize = this.CroppedImage.RenderSize; if (x > this.offset.X + renderSize.Width - 24) { Size size = this.CroppedImage.RenderSize; x = this.offset.X + size.Width - 24; realLeft = (x + 24 - this.PinTL.RealLeft) / rate + this.PinTL.RealTop - 24; } Size renderSize1 = this.CroppedImage.RenderSize; if (realLeft > this.offset.Y + renderSize1.Height - 24) { Size size1 = this.CroppedImage.RenderSize; realLeft = this.offset.Y + size1.Height - 24; x = (realLeft + 24 - this.PinTL.RealTop) * rate + this.PinTL.RealLeft - 24; } if (x < this.PinTL.RealLeft + this.minWidth - 24) { x = this.PinTL.RealLeft + this.minWidth - 24; realLeft = this.PinTL.RealTop + this.minHeight - 24; } this.PinTR.RealLeft = x; this.PinBL.RealTop = realLeft; this.PinBR.RealLeft = x; this.PinBR.RealTop = realLeft; } if (this.activePin.Equals(this.TR)) { double realTop = y; double num = this.PinBL.RealTop - (realTop + 24 - this.PinBL.RealLeft) / rate + 24; Size renderSize2 = this.CroppedImage.RenderSize; if (realTop > this.offset.X + renderSize2.Width - 24) { Size size2 = this.CroppedImage.RenderSize; realTop = this.offset.X + size2.Width - 24; num = this.PinBL.RealTop - (realTop + 24 - this.PinBL.RealLeft) / rate + 24; } if (num < this.offset.Y) { num = this.offset.Y; realTop = (this.PinBL.RealTop - num + 24) * rate + this.PinBL.RealLeft - 24; } if (realTop < this.PinBL.RealLeft + this.minWidth - 24) { realTop = this.PinBL.RealLeft + this.minWidth - 24; num = this.PinBL.RealTop - this.minHeight + 24; } this.PinBR.RealLeft = realTop; this.PinTL.RealTop = num; this.PinTR.RealLeft = realTop; this.PinTR.RealTop = num; } if (this.activePin.Equals(this.TL)) { double realLeft1 = y; double realTop1 = this.PinBR.RealTop - (this.PinBR.RealLeft + 24 - realLeft1) / rate + 24; if (realLeft1 > this.PinBR.RealLeft + 24 - this.minWidth) { realLeft1 = this.PinBR.RealLeft + 24 - this.minWidth; realTop1 = this.PinBR.RealTop + 24 - this.minHeight; } if (realTop1 < this.offset.Y) { realTop1 = this.offset.Y; realLeft1 = this.PinBR.RealLeft + 24 - (this.PinBR.RealTop - realTop1 + 24) * rate; } if (realLeft1 < this.offset.X) { realLeft1 = this.offset.X; realTop1 = this.PinBR.RealTop - (this.PinBR.RealLeft + 24 - realLeft1) / rate + 24; } this.PinBL.RealLeft = realLeft1; this.PinTR.RealTop = realTop1; this.PinTL.RealLeft = realLeft1; this.PinTL.RealTop = realTop1; } if (this.activePin.Equals(this.BL)) { double x1 = y; double num1 = (this.PinTR.RealLeft + 24 - x1) / rate + this.PinTR.RealTop - 24; if (x1 > this.PinTR.RealLeft + 24 - this.minWidth) { x1 = this.PinTR.RealLeft + 24 - this.minWidth; num1 = this.PinTR.RealTop + this.minHeight - 24; } Size renderSize3 = this.CroppedImage.RenderSize; if (num1 > this.offset.Y + renderSize3.Height - 24) { Size size3 = this.CroppedImage.RenderSize; num1 = this.offset.Y + size3.Height - 24; x1 = this.PinTR.RealLeft - (num1 + 24 - this.PinTR.RealTop) * rate + 24; } if (x1 < this.offset.X) { x1 = this.offset.X; num1 = (this.PinTR.RealLeft + 24 - x1) / rate + this.PinTR.RealTop - 24; } this.PinTL.RealLeft = x1; this.PinBR.RealTop = num1; this.PinBL.RealLeft = x1; this.PinBL.RealTop = num1; } } public static WriteableBitmap writeableBmp; private async void AppBarButton_Crop_Click(object sender, RoutedEventArgs e) { } private void AppBarButton_Accept_Click(object sender, RoutedEventArgs e) { }