最近在家闭门造车,写了一个简单的GIF制作工具,效果如下:
下面介绍下实现步骤:
首先是绘图控件部分功能,实现了图片与坐标宽高之间的绑定。
1、MyImage类,由于底图不可选中编辑,所以加入了IsCanClick是否可以点击选中标志,在鼠标操作中加入判断
if (!IsCanClick) return;
其他与WPF中GDI+图形图像的绘制:(七)绘制图像——鼠标拖动改变位置和大小中一致,这里不再赘述。
2、由于要对绘图控件中的MyImage进行绑定,所以新建BindItemClass.cs类
public partial class BindItemClass
{
///
/// 图源
///
public BitmapImage ImgSource { get; set; }
///
/// 是否是底图
///
public bool IsBackground { get; set; }
///
/// 层级
///
public int ZIndex { get; set; }
///
/// X坐标
///
public double LocationX { get; set; }
///
/// Y坐标
///
public double LocationY { get; set; }
///
/// 宽
///
public double ItemWidth { get; set; }
///
/// 高
///
public double ItemHeight { get; set; }
///
/// X坐标绑定控件
///
public object BindControlLocationX { get; set; }
///
/// Y坐标绑定控件
///
public object BindControlLocationY { get; set; }
///
/// 宽绑定控件
///
public object BindControlItemWidth { get; set; }
///
/// 高绑定控件
///
public object BindControlItemHeight { get; set; }
}
3、MyCanvas自定义控件的封装
新建自定义控件MyCanvas,添加MouseLeftButtonDown,MouseLeftButtonUp,MouseMove事件,xaml窗体代码:
其交互逻辑与博文WPF中GDI+图形图像的绘制:(八)位置坐标和宽高与控件绑定展示中一致,这里对其做了功能完善与封装 给出源码:
///
/// MyCanvas.xaml 的交互逻辑
///
public partial class MyCanvas : Canvas
{
private Point pBefore = new Point();//鼠标点击前坐标
private Point eBefore = new Point();//图片移动前坐标
private double wBefore;//图片改变大小前宽
private double hBefore;//图片改变大小前高
private int minImgValue = 10;//图片最小宽高
private bool IsCanMove = false;//是否可以移动
public event MouseEventHandler OnChangeLocationX;// 坐标改变事件
public event MouseEventHandler OnChangeLocationY;// 坐标改变事件
public event MouseEventHandler OnChangeW;//宽高改变事件
public event MouseEventHandler OnChangeH;//宽高改变事件
public MyCanvas()
{
InitializeComponent();
}
#region 提供给外部的调用方法
///
/// 展示素材
///
public void ShowItem(BindItemClass item)
{
if (item == null) return;
MyImage imgPic = new MyImage();
imgPic.Tag = item;
imgPic.Source = item.ImgSource;
imgPic.Width = item.ItemWidth;
imgPic.Height = item.ItemHeight;
imgPic.IsCanClick = !item.IsBackground;
Canvas.SetLeft(imgPic, item.LocationX);
Canvas.SetTop(imgPic, item.LocationY);
Canvas.SetZIndex(imgPic, item.ZIndex);
this.Children.Add(imgPic);
}
///
/// 清除底图
///
public void ClearBackground()
{
foreach (var item in this.Children)
{
MyImage img = item as MyImage;
if (img != null && !img.IsCanClick)
{
this.Children.Remove(img);
return;
}
}
}
///
/// 清除所有元素
///
public void ClearFrameItem()
{
this.Children.Clear();
}
///
/// 改变X坐标
///
public void ChangeXByNud(System.Windows.Forms.NumericUpDown nudX)
{
if (IsCanMove) return;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(this); i++)
{
if (VisualTreeHelper.GetChild(this, i).GetType() == typeof(MyImage))
{
MyImage child = (MyImage)VisualTreeHelper.GetChild(this, i);
if ((child.IsSelect) && child.Tag != null)
{
object objX = (object)((BindItemClass)child.Tag).BindControlLocationX;
if (objX != null)
{
Canvas.SetLeft(child, Convert.ToDouble(nudX.Value));
child.InvalidateVisual();
OnChangeLocationX?.Invoke(child.Tag, null);
}
}
}
}
}
///
/// 改变Y坐标
///
public void ChangeYByNud(System.Windows.Forms.NumericUpDown nudY)
{
if (IsCanMove) return;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(this); i++)
{
if (VisualTreeHelper.GetChild(this, i).GetType() == typeof(MyImage))
{
MyImage child = (MyImage)VisualTreeHelper.GetChild(this, i);
if ((child.IsSelect) && child.Tag != null)
{
object objY = (object)((BindItemClass)child.Tag).BindControlLocationY;
if (objY != null)
{
Canvas.SetTop(child, Convert.ToDouble(nudY.Value));
child.InvalidateVisual();
OnChangeLocationY?.Invoke(child.Tag, null);
}
}
}
}
}
///
/// 改变宽
///
public void ChangeWByNud(System.Windows.Forms.NumericUpDown nudW)
{
if (IsCanMove) return;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(this); i++)
{
if (VisualTreeHelper.GetChild(this, i).GetType() == typeof(MyImage))
{
MyImage child = (MyImage)VisualTreeHelper.GetChild(this, i);
if ((child.IsSelect) && child.Tag != null)
{
object objW = (object)((BindItemClass)child.Tag).BindControlItemWidth;
if (objW != null)
{
child.Width = Convert.ToDouble(nudW.Value);
child.InvalidateVisual();
OnChangeW?.Invoke(child.Tag, null);
}
}
}
}
}
///
/// 改变高
///
public void ChangeHByNud(System.Windows.Forms.NumericUpDown nudH)
{
if (IsCanMove) return;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(this); i++)
{
if (VisualTreeHelper.GetChild(this, i).GetType() == typeof(MyImage))
{
MyImage child = (MyImage)VisualTreeHelper.GetChild(this, i);
if ((child.IsSelect) && child.Tag != null)
{
object objH = (object)((BindItemClass)child.Tag).BindControlItemHeight;
if (objH != null)
{
child.Height = Convert.ToDouble(nudH.Value);
child.InvalidateVisual();
OnChangeH?.Invoke(child.Tag, null);
}
}
}
}
}
#endregion
///
/// 鼠标按下
///
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.OriginalSource.GetType() == typeof(MyImage))
{
MyImage img = (MyImage)e.OriginalSource;
if (img != null && !img.IsCanClick) return;
//获取点击前鼠标坐标
this.pBefore = e.GetPosition(this);
//获取点击图片的坐标和位置
this.eBefore = new Point(Canvas.GetLeft(img), Canvas.GetTop(img));
this.wBefore = img.Width;
this.hBefore = img.Height;
//设置为可移动
IsCanMove = true;
//鼠标捕获此图片
img.CaptureMouse();
img.IsSelect = true;
img.InvalidateVisual();
//展示XY坐标
ShowX(img, e);
ShowY(img, e);
//展示宽高
ShowW(img, e);
ShowH(img, e);
SetOtherUnSelect(img);
//改变鼠标样式
this.Cursor = System.Windows.Input.Cursors.SizeAll;
}
else
{
SetOtherUnSelect();
}
}
///
/// 鼠标抬起
///
private void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (e.OriginalSource.GetType() == typeof(MyImage))
{
MyImage img = (MyImage)e.OriginalSource;
//设置为不可移动
IsCanMove = false;
//鼠标释放此图片
img.ReleaseMouseCapture();
img.InvalidateVisual();
this.Cursor = System.Windows.Input.Cursors.Arrow;
}
}
///
/// 鼠标移动
///
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (!IsCanMove)
return;
if (e.OriginalSource != null && e.LeftButton == MouseButtonState.Pressed)
{
if (e.OriginalSource.GetType() == typeof(MyImage))
{
MyImage img = (MyImage)e.OriginalSource;
if (IsCanMove && img != null)
{
MoveChange(e, img.changeType);
}
}
else
{
base.OnMouseMove(e);
}
}
else
this.Cursor = System.Windows.Input.Cursors.Arrow;
}
///
/// 移动改变坐标或大小
///
private void MoveChange(System.Windows.Input.MouseEventArgs e, ChangeType changeType)
{
try
{
switch (changeType)
{
case ChangeType.ChangeLeftTop:
setLTvp(e);
break;
case ChangeType.ChangeRightTop:
setRTvp(e);
break;
case ChangeType.ChangeRightBottom:
setRBvp(e);
break;
case ChangeType.ChangeLeftBottom:
setLBvp(e);
break;
case ChangeType.Move:
MyImage img = (MyImage)e.OriginalSource;
if (img != null)
MoveImage(e);
break;
}
}
catch (Exception ex)
{
}
}
///
/// 移动对象
///
public void MoveImage(System.Windows.Input.MouseEventArgs e)
{
MyImage img = (MyImage)e.OriginalSource;
//获取鼠标移动中的坐标
Point p = e.GetPosition(this);
//计算拖拽距离
double dragx = p.X - pBefore.X;
double dragy = p.Y - pBefore.Y;
//当拖拽距离大于一定范围时改变控件位置
if (Math.Abs(dragx) > 5 || Math.Abs(dragy) > 5)
{
Canvas.SetLeft(img, eBefore.X + dragx);
Canvas.SetTop(img, eBefore.Y + dragy);
img.InvalidateVisual();
//展示XY坐标
ShowX(img, e);
ShowY(img, e);
}
}
///
/// 左上角拖动
///
public void setLTvp(System.Windows.Input.MouseEventArgs e)
{
//获取鼠标移动中的坐标
Point p = e.GetPosition(this);
if (e.OriginalSource.GetType() == typeof(MyImage))
{
MyImage img = (MyImage)e.OriginalSource;
double changeX = p.X - pBefore.X;
double changeY = p.Y - pBefore.Y;
if ((wBefore - changeX) > minImgValue)
{
Canvas.SetLeft(img, eBefore.X + changeX);
img.Width = wBefore - changeX;
}
else
{
img.Width = minImgValue;
}
if ((hBefore - changeY) > minImgValue)
{
Canvas.SetTop(img, eBefore.Y + changeY);
img.Height = hBefore - changeY;
}
else
{
img.Height = minImgValue;
}
img.InvalidateVisual();
//展示XY坐标
ShowX(img, e);
ShowY(img, e);
//展示宽高
ShowW(img, e);
ShowH(img, e);
}
}
///
/// 右上角拖动
///
public void setRTvp(System.Windows.Input.MouseEventArgs e)
{
//获取鼠标移动中的坐标
Point p = e.GetPosition(this);
if (e.OriginalSource.GetType() == typeof(MyImage))
{
MyImage img = (MyImage)e.OriginalSource;
double changeX = p.X - pBefore.X;
double changeY = p.Y - pBefore.Y;
img.Width = (wBefore + changeX) > minImgValue ? wBefore + changeX : minImgValue;
if ((hBefore - changeY) > minImgValue)
{
Canvas.SetTop(img, eBefore.Y + changeY);
img.Height = hBefore - changeY;
}
else
{
img.Height = minImgValue;
}
img.InvalidateVisual();
//展示Y坐标
ShowY(img, e);
//展示宽高
ShowW(img, e);
ShowH(img, e);
}
}
///
/// 左下角拖动
///
public void setLBvp(System.Windows.Input.MouseEventArgs e)
{
//获取鼠标移动中的坐标
Point p = e.GetPosition(this);
if (e.OriginalSource.GetType() == typeof(MyImage))
{
MyImage img = (MyImage)e.OriginalSource;
double changeX = p.X - pBefore.X;
double changeY = p.Y - pBefore.Y;
if ((wBefore - changeX) > minImgValue)
{
Canvas.SetLeft(img, eBefore.X + changeX);
img.Width = wBefore - changeX;
}
else
{
img.Width = minImgValue;
}
img.Height = (hBefore + changeY) > minImgValue ? hBefore + changeY : minImgValue;
img.InvalidateVisual();
//展示XY坐标
ShowX(img, e);
ShowY(img, e);
//展示宽高
ShowW(img, e);
ShowH(img, e);
}
}
///
/// 右下角拖动
///
public void setRBvp(System.Windows.Input.MouseEventArgs e)
{
//获取鼠标移动中的坐标
Point p = e.GetPosition(this);
if (e.OriginalSource.GetType() == typeof(MyImage))
{
MyImage img = (MyImage)e.OriginalSource;
double changeX = p.X - pBefore.X;
double changeY = p.Y - pBefore.Y;
img.Width = (wBefore + changeX) > minImgValue ? wBefore + changeX : minImgValue;
img.Height = (hBefore + changeY) > minImgValue ? hBefore + changeY : minImgValue;
img.InvalidateVisual();
//展示宽高
ShowW(img, e);
ShowH(img, e);
}
}
///
/// 设置其他为未选择状态
///
public void SetOtherUnSelect(object myImage = null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(this); i++)
{
if (VisualTreeHelper.GetChild(this, i).GetType() == typeof(MyImage))
{
MyImage child = (MyImage)VisualTreeHelper.GetChild(this, i);
if (myImage == null)
{
child.IsSelect = false;
child.InvalidateVisual();
}
else if (myImage != child)
{
if (child.IsSelect)
{
child.IsSelect = false;
child.InvalidateVisual();
}
}
}
}
}
///
/// 展示X坐标
///
private void ShowX(MyImage img, MouseEventArgs e = null)
{
if (img.Tag != null)
{
object nud = (object)((BindItemClass)img.Tag).BindControlLocationX;
if (nud != null && nud.GetType() == typeof(System.Windows.Forms.NumericUpDown))
{
((System.Windows.Forms.NumericUpDown)nud).Value = Convert.ToDecimal(Canvas.GetLeft(img));
OnChangeLocationX?.Invoke(img.Tag, null);
}
}
}
///
/// 展示Y坐标
///
private void ShowY(MyImage img, MouseEventArgs e = null)
{
if (img.Tag != null)
{
object nud = (object)((BindItemClass)img.Tag).BindControlLocationY;
if (nud != null && nud.GetType() == typeof(System.Windows.Forms.NumericUpDown))
{
((System.Windows.Forms.NumericUpDown)nud).Value = Convert.ToDecimal(Canvas.GetTop(img));
OnChangeLocationY?.Invoke(img.Tag, null);
}
}
}
///
/// 展示img宽
///
private void ShowW(MyImage img, MouseEventArgs e = null)
{
if (img.Tag != null)
{
object nud = (object)((BindItemClass)img.Tag).BindControlItemWidth;
if (nud != null && nud.GetType() == typeof(System.Windows.Forms.NumericUpDown))
{
((System.Windows.Forms.NumericUpDown)nud).Value = Convert.ToDecimal(img.Width);
OnChangeW?.Invoke(img.Tag, null);
}
}
}
///
/// 展示img高
///
private void ShowH(MyImage img, MouseEventArgs e = null)
{
if (img.Tag != null)
{
object nud = (object)((BindItemClass)img.Tag).BindControlItemHeight;
if (nud != null && nud.GetType() == typeof(System.Windows.Forms.NumericUpDown))
{
((System.Windows.Forms.NumericUpDown)nud).Value = Convert.ToDecimal(img.Height);
OnChangeH?.Invoke(img.Tag, null);
}
}
}
}
相关博文:
WPF一个完整的GIF制作实例(Part1:绘图控件的封装)
WPF一个完整的GIF制作实例(Part2:时间轴控件的实现)
WPF一个完整的GIF制作实例(Part3:生成GIF)