WPF 自定义图片剪切器 - 头像剪切(扩展与完善、实时截图)
原文:WPF 自定义图片剪切器 - 头像剪切(扩展与完善、实时截图)
一、说明:上一次写的”WPF
自定义图片剪切器 - 头像剪切。你懂得“存在明显的缺陷,由于篇幅较长。重新写了一篇新的。
问题的原因:由于是对图片文件进行剪切处理,当图片加载后变形的话,处理起来明显的有错误!
解决办法:重新计算比例。但是有个问题就是在原来的基础上重新计算,计算量会相当复杂。因为整个截图区域就那么大,是固 定的,而图片可大可小,你要是想正确获取加载后的图片与截图区域的比例将会变得相当麻烦。
所以,本次采用一个最基本的设计技巧,就是 截图区域 = 图片加载后的区域 !将截图控件ImageDealerUnsafe按照大小可变化的情况封装在自定义控件ImageDealer里,通过自定义控件ImageDealer封装截图控件的调用接口,而ImageDealerUnsafe。
二、关于截图控件(ImageDealerUnsafe) 用户不应调用该控件的任何方法、仅供ImageDealer调用
1、截图控件 ImageDealerUnsafe XAML
<UserControl x:Class="DialogEx.Controls.Unsafe.ImageDealerUnsafe"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Background="Transparent"
SnapsToDevicePixels="True"
PreviewMouseDown="UserControl_MouseDown" PreviewMouseUp="UserControl_MouseUp" MouseLeave="UserControl_MouseLeave" PreviewMouseMove="UserControl_MouseMove"
>
<Grid Name="MainGrid" >
<Image Name="SoureceImage" Stretch="Uniform"></Image>
<Border Name="ImageArea" BorderBrush="Red" BorderThickness="1,1,1,1" Panel.ZIndex="5" Margin="50" SizeChanged="ImageArea_SizeChanged">
<Grid >
<Rectangle Name="R_LeftUp" Width="5" Height="5" Margin="-3" VerticalAlignment="Top" HorizontalAlignment="Left" Fill="White" Panel.ZIndex="0" Cursor="SizeNWSE"/>
<Rectangle Name="R_Up" Width="5" Height="5" Margin="-3" VerticalAlignment="Top" HorizontalAlignment="Center" Fill="White" Panel.ZIndex="0" Cursor="SizeNS"/>
<Rectangle Name="R_RightUp" Width="5" Height="5" Margin="-3" VerticalAlignment="Top" HorizontalAlignment="Right" Fill="White" Panel.ZIndex="0" Cursor="SizeNESW"/>
<Rectangle Name="R_Right" Width="5" Height="5" Margin="-3" VerticalAlignment="Center" HorizontalAlignment="Right" Fill="White" Panel.ZIndex="0" Cursor="SizeWE"/>
<Rectangle Name="R_RightDown" Width="5" Height="5" Margin="-3" VerticalAlignment="Bottom" HorizontalAlignment="Right" Fill="White" Panel.ZIndex="0" Cursor="SizeNWSE"/>
<Rectangle Name="R_Down" Width="5" Height="5" Margin="-3" VerticalAlignment="Bottom" HorizontalAlignment="Center" Fill="White" Panel.ZIndex="0" Cursor="SizeNS"/>
<Rectangle Name="R_LeftDown" Width="5" Height="5" Margin="-3" VerticalAlignment="Bottom" HorizontalAlignment="Left" Fill="White" Panel.ZIndex="0" Cursor="SizeNESW"/>
<Rectangle Name="R_Left" Width="5" Height="5" Margin="-3" VerticalAlignment="Center" HorizontalAlignment="Left" Fill="White" Panel.ZIndex="0" Cursor="SizeWE"/>
<!--<GridSplitter Height="5" Width="5" VerticalAlignment="Bottom" HorizontalAlignment="Stretch"></GridSplitter>-->
</Grid>
</Border>
</Grid>
</UserControl>
2、截图控件ImageDealerUnsafeCS
using DialogEx.Class;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace DialogEx.Controls.Unsafe
{
/// <summary>
/// ImageDealerUnsafe.xaml 的交互逻辑
/// </summary>
public partial class ImageDealerUnsafe : UserControl
{
#region 公共字段
//截图回调
public delegate void CutImageDelegate(BitmapSource bit);
public CutImageDelegate OnCutImage;
//图片原
private BitmapImage _BitSource;
public BitmapImage BitSource
{
get { return this._BitSource; }
set
{
this._BitSource = value;
this.SoureceImage.Source = value;
}
}
#endregion
#region 依赖属性
/// <summary>
/// 边距
/// </summary>
public double MaxMargin = 2;
//public Brush BorderBrush;
#endregion
#region ==私有字段==
/// <summary>
/// 鼠标样式
/// </summary>
private Cursor MouseCursor = Cursors.Arrow;
/// <summary>
/// 鼠标位置
/// </summary>
private MouseLocationEnum MouseLocation = MouseLocationEnum.None;
/// <summary>
/// 鼠标行为
/// </summary>
private MouseActionEx Action { get; set; }
/// <summary>
/// 边框粗细
/// </summary>
private double BorderWidth = 1;
/// <summary>
/// 拖拽前鼠标按下位置
/// </summary>
private Point MouseDownPoint;
/// <summary>
/// 拖拽前控件位置
/// </summary>
private Point MouseDownLocate;
#endregion
#region ==方法==
public ImageDealerUnsafe()
{
InitializeComponent();
}
/// <summary>
/// 计算区域圆点及宽高
/// </summary>
/// <param name="MouseButtonLocate">鼠标相对背景MainGrid位置</param>
/// <param name="IsRectangle">是否正方形</param>
/// <returns>NULL 或 具体值</returns>
private RectangleAreaModel CalculatedArea(Point MouseButtonLocate, bool IsRectangle)
{
Point Locate = this.ImageArea.TransformToAncestor((UIElement)this.MainGrid).Transform(new Point(0, 0));
//边框宽度
double BorderWidth = this.BorderWidth;
//整体宽度
double RectWidth = this.ImageArea.ActualWidth;
//整体高度
double RectHeight = this.ImageArea.ActualHeight;
//裁剪区域
Point OriginalPoint = new Point(0, 0);//圆点坐标
Point TheoryPoint = new Point(0, 0); //理论坐标
double TheoryWidth = 0; //理论宽度
double TheoryHeight = 0; //理论高度
switch (MouseLocation)
{
case MouseLocationEnum.Left:
{
this.Cursor = Cursors.SizeWE;
OriginalPoint = new Point(Locate.X + RectWidth - BorderWidth / 2, Locate.Y + RectHeight / 2);//右中部位置
TheoryWidth = OriginalPoint.X - MouseButtonLocate.X + BorderWidth;
TheoryHeight = IsRectangle == true ? TheoryWidth : RectHeight;
TheoryPoint = new Point(OriginalPoint.X + BorderWidth / 2 - TheoryWidth, OriginalPoint.Y - TheoryHeight / 2);
}
break;
case MouseLocationEnum.LeftUp:
{
this.Cursor = Cursors.SizeNWSE;
OriginalPoint = new Point(Locate.X + RectWidth - BorderWidth / 2, Locate.Y + RectHeight - BorderWidth / 2);//右下部位置
TheoryWidth = OriginalPoint.X - MouseButtonLocate.X + BorderWidth;
TheoryHeight = IsRectangle == true ? TheoryWidth : OriginalPoint.Y - MouseButtonLocate.Y + BorderWidth;
TheoryPoint = new Point(OriginalPoint.X + BorderWidth / 2 - TheoryWidth, OriginalPoint.Y + BorderWidth / 2 - TheoryHeight);
}
break;
case MouseLocationEnum.Up:
{
this.Cursor = Cursors.SizeNS;
OriginalPoint = new Point(Locate.X + RectWidth / 2, Locate.Y + RectHeight - BorderWidth / 2);//下中部位置
TheoryHeight = OriginalPoint.Y - MouseButtonLocate.Y + BorderWidth;
TheoryWidth = IsRectangle == true ? TheoryHeight : RectWidth;
TheoryPoint = new Point(OriginalPoint.X - TheoryWidth / 2, OriginalPoint.Y + BorderWidth / 2 - TheoryHeight);
}
break;
case MouseLocationEnum.RightUp:
{
this.Cursor = Cursors.SizeNESW;
OriginalPoint = new Point(Locate.X + BorderWidth / 2, Locate.Y + RectHeight - BorderWidth / 2);//左下部位置
TheoryWidth = MouseButtonLocate.X - OriginalPoint.X + BorderWidth;
TheoryHeight = IsRectangle == true ? TheoryWidth : MouseButtonLocate.Y - OriginalPoint.Y + BorderWidth;
TheoryPoint = new Point(OriginalPoint.X - BorderWidth / 2, OriginalPoint.Y + BorderWidth / 2 - TheoryHeight);
}
break;
case MouseLocationEnum.Right:
{
this.Cursor = Cursors.SizeWE;
OriginalPoint = new Point(Locate.X + BorderWidth / 2, Locate.Y + RectHeight / 2);//左中部位置
TheoryWidth = MouseButtonLocate.X - OriginalPoint.X + BorderWidth;
TheoryHeight = IsRectangle == true ? TheoryWidth : RectHeight;
TheoryPoint = new Point(OriginalPoint.X - BorderWidth / 2, OriginalPoint.Y - TheoryHeight / 2);
}
break;
case MouseLocationEnum.RightDown:
{
this.Cursor = Cursors.SizeNWSE;
OriginalPoint = new Point(Locate.X + BorderWidth / 2, Locate.Y + BorderWidth / 2);//左上部位置
TheoryWidth = MouseButtonLocate.X - OriginalPoint.X + BorderWidth;
TheoryHeight = IsRectangle == true ? TheoryWidth : MouseButtonLocate.Y - OriginalPoint.Y + BorderWidth;
TheoryPoint = new Point(OriginalPoint.X - BorderWidth / 2, OriginalPoint.Y - BorderWidth / 2);
}
break;
case MouseLocationEnum.Down:
{
this.Cursor = Cursors.SizeNS;
OriginalPoint = new Point(Locate.X + RectWidth / 2, Locate.Y + BorderWidth / 2);//上中部位置
TheoryHeight = MouseButtonLocate.Y - OriginalPoint.Y + BorderWidth;
TheoryWidth = IsRectangle == true ? TheoryHeight : RectWidth;
TheoryPoint = new Point(OriginalPoint.X - TheoryWidth / 2, OriginalPoint.Y - BorderWidth / 2);
}
break;
case MouseLocationEnum.LeftDown:
{
this.Cursor = Cursors.SizeNESW;
OriginalPoint = new Point(Locate.X + RectWidth - BorderWidth / 2, Locate.Y + BorderWidth / 2);//右上部位置
TheoryWidth = OriginalPoint.X - MouseButtonLocate.X + BorderWidth;
TheoryHeight = IsRectangle == true ? TheoryWidth : OriginalPoint.Y - MouseButtonLocate.Y + BorderWidth;
TheoryPoint = new Point(OriginalPoint.X + BorderWidth / 2 - TheoryWidth, OriginalPoint.Y - BorderWidth / 2);
}
break;
default:
return null;
}
return new RectangleAreaModel()
{
X = TheoryPoint.X,
Y = TheoryPoint.Y,
Width = TheoryWidth,
Height = TheoryHeight
};
}
/// <summary>
/// 图片剪切
/// </summary>
public void CutImage()
{
if (this.BitSource != null)
{
try
{
double ImageAreaWidth = this.ImageArea.ActualWidth;
double ImageAreaHeight = this.ImageArea.ActualHeight;
double GridWidth = this.MainGrid.ActualWidth;
double GridHeight = this.MainGrid.ActualHeight;
BitmapSource source = (BitmapSource)this.BitSource;
//计算比例
Point Locate = this.ImageArea.TransformToAncestor((UIElement)this.MainGrid).Transform(new Point(0, 0));
int dWidth = (int)((ImageAreaWidth * 1.0 / GridWidth) * source.PixelWidth);
int dHeight = (int)((ImageAreaHeight * 1.0 / GridHeight) * source.PixelHeight);
int dLeft = (int)((Locate.X * 1.0 / GridWidth) * source.PixelWidth);
int dTop = (int)((Locate.Y * 1.0 / GridHeight) * source.PixelHeight);
//像素区域
Int32Rect cutRect = new Int32Rect(dLeft, dTop, dWidth, dHeight);
//数组字节数
int stride = source.Format.BitsPerPixel * cutRect.Width / 8;
byte[] data = new byte[cutRect.Height * stride];
source.CopyPixels(cutRect, data, stride, 0);
//创建
BitmapSource bit = BitmapSource.Create(dWidth, dHeight, 0, 0, PixelFormats.Bgr32, null, data, stride);
//通知订阅
if (this.OnCutImage != null)
{
OnCutImage(bit);
}
}
catch
{
}
}
}
/// <summary>
/// 视图转图片
/// </summary>
/// <param name="vsual"></param>
/// <param name="nLeft"></param>
/// <param name="nTop"></param>
/// <param name="nWidth"></param>
/// <param name="nHeight"></param>
/// <returns></returns>
private RenderTargetBitmap RenderVisaulToBitmap(Visual vsual,int nLeft, int nTop,int nWidth, int nHeight)
{
var rtb = new RenderTargetBitmap(nWidth, nHeight, nLeft, nTop, PixelFormats.Default);
rtb.Render(vsual);
return rtb;
}
/// <summary>
/// Bitmap转图片
/// </summary>
/// <param name="bmp"></param>
/// <returns></returns>
public BitmapSource ToBitmapSource(System.Drawing.Bitmap bmp)
{
BitmapSource returnSource;
try
{
returnSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
}
catch
{
returnSource = null;
}
return returnSource;
}
#endregion
#region ==事件==
//按下鼠标
private void UserControl_MouseDown(object sender, MouseButtonEventArgs e)
{
this.MouseLocation = Class.MouseLocationEnum.None;
if (e.OriginalSource.GetType() == typeof(Rectangle))
{
Rectangle Act = e.OriginalSource as Rectangle;
switch (Act.Name)
{
case "R_Left": MouseLocation = Class.MouseLocationEnum.Left; break;
case "R_LeftUp": MouseLocation = Class.MouseLocationEnum.LeftUp; break;
case "R_Up": MouseLocation = Class.MouseLocationEnum.Up; break;
case "R_RightUp": MouseLocation = Class.MouseLocationEnum.RightUp; break;
case "R_Right": MouseLocation = Class.MouseLocationEnum.Right; break;
case "R_RightDown": MouseLocation = Class.MouseLocationEnum.RightDown; break;
case "R_Down": MouseLocation = Class.MouseLocationEnum.Down; break;
case "R_LeftDown": MouseLocation = Class.MouseLocationEnum.LeftDown; break;
default: MouseLocation = Class.MouseLocationEnum.None; break;
}
this.Action = MouseActionEx.Drag;
}
else
{
this.MouseDownPoint = Mouse.GetPosition(e.Source as FrameworkElement);//WPF方法
this.MouseDownLocate = this.ImageArea.TransformToAncestor((UIElement)this.MainGrid).Transform(new Point(0, 0));
if ((this.MouseDownLocate.X < this.MouseDownPoint.X && this.MouseDownPoint.X < this.MouseDownLocate.X + this.ImageArea.ActualWidth) &&
(this.MouseDownLocate.Y < this.MouseDownPoint.Y && this.MouseDownPoint.Y < this.MouseDownLocate.Y + this.ImageArea.ActualHeight)
)
{
this.Action = MouseActionEx.DragMove;
}
}
}
//弹起鼠标
private void UserControl_MouseUp(object sender, MouseButtonEventArgs e)
{
this.Action = MouseActionEx.None;
this.Cursor = Cursors.Arrow;
}
//移动鼠标
private void UserControl_MouseMove(object sender, MouseEventArgs e)
{
//鼠标相对空间区域位置
Point MousePoint = e.GetPosition((IInputElement)this.MainGrid);
Point ImageLocate= this.ImageArea.TransformToAncestor((UIElement)this.MainGrid).Transform(new Point(0, 0));
if (ImageLocate.X <= MousePoint.X && MousePoint.X <= ImageLocate.X + this.ImageArea.ActualWidth &&
ImageLocate.Y <= MousePoint.Y && MousePoint.Y <= ImageLocate.Y + this.ImageArea.ActualHeight)
{
this.Cursor = Cursors.Hand;
}
else
{
this.Cursor = Cursors.Arrow;
}
//边框拉伸
if (this.Action == MouseActionEx.Drag)
{
this.Cursor = this.MouseCursor;
//剪辑图片区域宽高
double ImageAreaWidth = this.ImageArea.ActualWidth;
double ImageAreaHeight = this.ImageArea.ActualHeight;
//裁剪区域理论位置
RectangleAreaModel Model = this.CalculatedArea(MousePoint, true);
if (Model != null)
{
//不能超出边界区域
if (Model.X + Model.Width + MaxMargin > this.ActualWidth ||
Model.Y + Model.Height + MaxMargin > this.ActualHeight ||
Model.X < MaxMargin ||
Model.Y < MaxMargin
)
{
this.Cursor = Cursors.Arrow;
this.Action = MouseActionEx.None;
return;
}
this.ImageArea.Width = Model.Width;
this.ImageArea.Height = Model.Height;
this.ImageArea.SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Left);
this.ImageArea.SetValue(VerticalAlignmentProperty, VerticalAlignment.Top);
this.ImageArea.SetValue(MarginProperty, new Thickness(Model.X, Model.Y, 0, 0));
CutImage();
}
}
else if (this.Action == MouseActionEx.DragMove)//拖动
{
double Left = this.MouseDownLocate.X + (MousePoint.X - MouseDownPoint.X);
double Top = this.MouseDownLocate.Y + (MousePoint.Y - MouseDownPoint.Y);
//不能超出边界区域
if (Left < MaxMargin ||
Top < MaxMargin ||
(Left + this.ImageArea.ActualWidth + MaxMargin) > this.ActualWidth ||
(Top + this.ImageArea.ActualHeight + MaxMargin) > this.ActualHeight)
{
this.Cursor = Cursors.Arrow;
this.Action = MouseActionEx.None;
return;
}
this.ImageArea.Width = this.ImageArea.ActualWidth;
this.ImageArea.Height = this.ImageArea.ActualHeight;
this.ImageArea.SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Left);
this.ImageArea.SetValue(VerticalAlignmentProperty, VerticalAlignment.Top);
this.ImageArea.SetValue(MarginProperty, new Thickness(Left, Top, 0, 0));
CutImage();
}
else
{
//this.Cursor = Cursors.Arrow;
}
}
//鼠标离开
private void UserControl_MouseLeave(object sender, MouseEventArgs e)
{
this.Action = MouseActionEx.None;
}
//加载完成后截图
private void ImageArea_SizeChanged(object sender, SizeChangedEventArgs e)
{
this.CutImage();
}
#endregion
}
}
三、封装的截图工具 ImageDealer
1、ImageDealer XAML
<UserControl x:Class="DialogEx.Controls.ImageDealer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Background="Transparent"
SnapsToDevicePixels="True"
Loaded="UserControl_Loaded"
>
<Grid Name="MainGrid" MinHeight="200" MinWidth="200" >
</Grid>
</UserControl>
2、ImageDealer CS
using DialogEx.Class;
using DialogEx.Controls.Unsafe;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace DialogEx.Controls
{
public partial class ImageDealer : UserControl
{
public static readonly RoutedEvent OnCutImagingEventHandler = EventManager.RegisterRoutedEvent("OnCutImaging", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ImageDealer));
#region 私有字段
/// <summary>
/// 截图控件
/// </summary>
private ImageDealerUnsafe _ImageDealerControl = new ImageDealerUnsafe();
/// <summary>
/// 图片源
/// </summary>
private BitmapImage _BitSource;
private int _ChangeMargin = 1;
#endregion
#region 公共字段
/// <summary>
/// 图片源
/// </summary>
public BitmapImage BitSource
{
get { return this._BitSource; }
set
{
this._BitSource = value;
this._ImageDealerControl.BitSource = value;
LocateInit();
}
}
/// <summary>
/// 截图事件
/// </summary>
public event RoutedEventHandler OnCutImaging
{
add { base.AddHandler(OnCutImagingEventHandler, value); }
remove { base.RemoveHandler(OnCutImagingEventHandler, value); }
}
#endregion
#region ==方法==
public ImageDealer()
{
InitializeComponent();
this._ImageDealerControl.OnCutImage += this.OnCutImage;
}
//外部截图
public void CutImage()
{
if (this.IsLoaded == true || this._ImageDealerControl == null)
{
this._ImageDealerControl.CutImage();
}
else
{
throw new Exception("尚未创建视图时无法截图!");
}
}
//截图控件位置初始化
private void LocateInit()
{
double Margin = 1;
if (this._BitSource != null)
{
double percent = 1;
//根据最小倍率放大截图控件
percent = (this._BitSource.PixelHeight * 1.0 / this.ActualHeight);
percent = percent < (this._BitSource.PixelWidth * 1.0 / this.ActualWidth) ? (this._BitSource.PixelWidth * 1.0 / this.ActualWidth) : percent;
this._ImageDealerControl.Width = this._BitSource.PixelWidth * 1.0 / percent;
this._ImageDealerControl.Height = this._BitSource.PixelHeight * 1.0 / percent;
//初始化截图方块
this._ImageDealerControl.ImageArea.Width = this._ImageDealerControl.ImageArea.Height = 100 + _ChangeMargin ;
_ChangeMargin = -_ChangeMargin;
this._ImageDealerControl.ImageArea.SetValue(VerticalAlignmentProperty, VerticalAlignment.Center);
this._ImageDealerControl.ImageArea.SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Center);
this._ImageDealerControl.ImageArea.SetValue(MarginProperty, new Thickness(0));
//截图控件相对父控件Margin
this._ImageDealerControl.Width -= 2 * Margin;
this._ImageDealerControl.Height -= 2 * Margin;
this._ImageDealerControl.SetValue(VerticalAlignmentProperty, VerticalAlignment.Center);
this._ImageDealerControl.SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Center);
this._ImageDealerControl.SetValue(MarginProperty, new Thickness(0));
}
}
#endregion
#region ==事件==
//截图回调
private void OnCutImage(BitmapSource bit)
{
RaiseEvent(new RoutedEventArgs(OnCutImagingEventHandler, bit));
}
//加载完成
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
if (this.MainGrid.Children.Contains(this._ImageDealerControl) == false)
{
this.MainGrid.Children.Add(this._ImageDealerControl);
this._ImageDealerControl.Width = this.ActualWidth;
this._ImageDealerControl.Height = this.ActualHeight;
this._ImageDealerControl.SetValue(VerticalAlignmentProperty, VerticalAlignment.Center);
this._ImageDealerControl.SetValue(HorizontalAlignmentProperty, HorizontalAlignment.Center);
this._ImageDealerControl.SetValue(MarginProperty, new Thickness(0));
}
}
#endregion
}
}
四、用户调用
1、外部调用 Windows 的 XAML
xmlns:MyControls="clr-namespace:DialogEx.Controls;assembly=DialogEx"
<!--图片选择区域-->
<pre name="code" class="csharp" style="font-size: 14px;"><Grid Visibility="{Binding ImageVisible}">
<MyControls:ImageDealer Panel.ZIndex="0" x:Name="ImageDealer" <span style="font-family: Arial, Helvetica, sans-serif;">OnCutImaging</span><span style="font-family: Arial, Helvetica, sans-serif;">="</span><span style="font-family: Arial, Helvetica, sans-serif;">OnCutImaging"></MyControls:ImageDealer></span>
</Grid>
2、Windows 的 CS
包含两个方法
1、获取截图控件的截取的图片(被动的接收通知、回调)
2、保存头像文件、(加载头像的时候请使用缓存方式
)
private BitmapSource CurBitMap;
<span style="white-space:pre"> </span>/// <summary>
<span style="white-space:pre"> </span>/// 截图中
<span style="white-space:pre"> </span>/// </summary>
<span style="white-space:pre"> </span>/// <param name="source"></param>
public void OnCutImaging(object source)
{
if (source != null && source.GetType() == typeof(RoutedEventArgs))
{
// if (((RoutedEventArgs)source).OriginalSource.GetType() == typeof(CroppedBitmap))
{
CurBitMap = (BitmapSource)((RoutedEventArgs)source).OriginalSource;
}
}
}
<span style="white-space:pre"> </span>/// <summary>
/// 保存头像
/// </summary>
public void btnCutPicture_Click()
{
string strFilePath = "F:\\1.png";
//try
{
if (File.Exists(strFilePath) == true)
{
File.Delete(strFilePath);
}
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(this.CurBitMap));
FileStream fileStream = new FileStream(strFilePath, FileMode.Create, FileAccess.ReadWrite);
encoder.Save(fileStream);
fileStream.Close();
}
//catch
{
}
}
WPF 自定义图片剪切器 - 头像剪切(扩展与完善、实时截图)的更多相关文章
- WPF 自定义图片按钮
此文档仅仅是一个BaseCode,已做后续查阅 XAML代码: <Button x:Class="IM.UI.UC.IM_ImageButton" xmlns="h ...
- WPF 自定义 MessageBox (相对完善版)
WPF 自定义 MessageBox (相对完善版) 基于WPF的自定义 MessageBox. 众所周知WPF界面美观.大多数WPF元素都可以简单的修改其样式,从而达到程序的风格统一.可是当 ...
- WPF 自定义 MessageBox (相对完善版 v1.0.0.6)
基于WPF的自定义 MessageBox. 众所周知WPF界面美观.大多数WPF元素都可以简单的修改其样式,从而达到程序的风格统一.可是当你不得不弹出一个消息框通知用户消息时(虽然很不建议在程序中频繁 ...
- vue自定义指令clickoutside使用以及扩展用法
vue自定义指令clickoutside使用以及扩展用法 产品使用vue+element作为前端框架.在功能开发过程中,难免遇到使用element的组件没办法满足特殊的业务需要,需要对其进行定制,例如 ...
- WPF自定义TextBox及ScrollViewer
原文:WPF自定义TextBox及ScrollViewer 寒假过完,在家真心什么都做不了,可能年龄大了,再想以前那样能专心坐下来已经不行了.回来第一件事就是改了项目的一个bug,最近又新增了一个新的 ...
- ASP.NET实现头像剪切保存
利用swfupload上传头像,利用Jcrop来实现头像在线选择,然后提交个ashx对原头像进行剪切.代码如下: default.aspx: <%@ Page Language="C# ...
- WPF 自定义ComboBox样式,自定义多选控件
原文:WPF 自定义ComboBox样式,自定义多选控件 一.ComboBox基本样式 ComboBox有两种状态,可编辑和不可编辑状态.通过设置IsEditable属性可以切换控件状态. 先看基本样 ...
- WPF 自定义MenuItem样式
原文:WPF 自定义MenuItem样式 一.前言 默认的MenuItem样式比较普通,这次自定义MenuItem的样式也只是对MenuItem的颜色风格进行变化.需要其他功能的变化,大家可以根据样式 ...
- 使用WPF将图片转变为灰度并加上水印并保存为文件
原文:使用WPF将图片转变为灰度并加上水印并保存为文件 运行效果: (上图中左下角为原图的缩小显示,By:Johnson为TextBlock)保存的结果图片:上图的"Test Words.& ...
随机推荐
- iOS开发Quartz2D之 七:雪花效果
#import "VCView.h" @implementation VCView -(void)awakeFromNib { //[NSTimer scheduledTimerW ...
- SAP 中的popup dialog (弹出对话框) 常见实现方法
方法1: FM:POPUP_TO_CONFIRM(标准对话弹出消息) 有三个button:YES-NO-CANL,可进行对应的逻辑推断 可设定标题,描写叙述问题,不方便对文本进行换行等排版,不能改 ...
- mysql分区功能(三个文件储存一张表)(分区作用)(分区方式)
mysql分区功能(三个文件储存一张表)(分区作用)(分区方式) 一.总结 1.mysql数据表的存储方式(三个文件储存一张表): 一张表主要对应着三个文件,一个是frm存放表结构的,一个是myd存放 ...
- 五一巨献,问答有礼,105QB送给IT互联网界的劳动人民
活动主题:五一巨献,问答有礼,105QB送给IT互联网界的劳动人民活动时间:4月30日晚上10点~5月2日晚上10点活动期数:第1期,20150401 奖品:105QB获奖人数:20人1~5:每人10 ...
- linux中竖线'|',双竖线‘||’,&和&&的意思
对于初学者来说这几个意思可能只知道其中几个的意思,下面我们来看一下. 1.竖线'|' ,在linux中是作为管道符的,将'|'前面命令的输出作为'|'后面的输入.举个例子 [18066609@root ...
- Android JNI编程(四)——C语言多级指针、数组取值、从控制台输入数组
版权声明:本文出自阿钟的博客,转载请注明出处:http://blog.csdn.net/a_zhon/. 目录(?)[+] 一:前面我们介绍了一级指针的相关概念和用发,今天我们就来说一说多级指针. 1 ...
- Android菜鸟的成长笔记(27)——SurfaceView的使用
前面有关自定义View中进行了绘图,但View的绘图机制存在如下缺陷: 1.View缺乏双缓冲机制. 2.当程序需要更新View上的图像时,程序必须重绘View上显示的整张图片. 3.新线程无法直接更 ...
- SSL/TLS协议运行机制的概述(转)
互联网的通信安全,建立在SSL/TLS协议之上. 本文简要介绍SSL/TLS协议的运行机制.文章的重点是设计思想和运行过程,不涉及具体的实现细节.如果想了解这方面的内容,请参阅RFC文档. 一.作用 ...
- php如何利用标准输入输出实现在一个字符串中计算某个字符出现的个数?
php如何利用标准输入输出实现在一个字符串中计算某个字符出现的个数? 一.总结 php实现计算字符个数(php标准输入和输出:fgets(STDIN) echo $output;) 1.php标准输 ...
- Android 解决Android的TextView和EditText换行问题
最近版本迭代的新增收货地址模块出现地址填写时点击换行,然后网络提交数据到后台,在地址列表查看地址时,也出现换行的问题. 问题效果图: 1.分析原因 用Google的DHC工具进行网络模拟请求,发现返回 ...