天天看点

WPF一个完整的GIF制作工具实例(Part1:绘图控件的封装)

最近在家闭门造车,写了一个简单的GIF制作工具,效果如下:

WPF一个完整的GIF制作工具实例(Part1:绘图控件的封装)

下面介绍下实现步骤:

首先是绘图控件部分功能,实现了图片与坐标宽高之间的绑定。

1、MyImage类,由于底图不可选中编辑,所以加入了IsCanClick是否可以点击选中标志,在鼠标操作中加入判断

if (!IsCanClick) return;
           

其他与WPF中GDI+图形图像的绘制:(七)绘制图像——鼠标拖动改变位置和大小中一致,这里不再赘述。

2、由于要对绘图控件中的MyImage进行绑定,所以新建BindItemClass.cs类

public partial class BindItemClass
    {
        /// <summary>
        /// 图源
        /// </summary>
        public BitmapImage ImgSource { get; set; }
        /// <summary>
        /// 是否是底图
        /// </summary>
        public bool IsBackground { get; set; }
        /// <summary>
        /// 层级
        /// </summary>
        public int ZIndex { get; set; }
        /// <summary>
        /// X坐标
        /// </summary>
        public double LocationX { get; set; }
        /// <summary>
        /// Y坐标
        /// </summary>
        public double LocationY { get; set; }
        /// <summary>
        /// 宽
        /// </summary>
        public double ItemWidth { get; set; }
        /// <summary>
        /// 高
        /// </summary>
        public double ItemHeight { get; set; }
        /// <summary>
        /// X坐标绑定控件
        /// </summary>
        public object BindControlLocationX { get; set; }
        /// <summary>
        /// Y坐标绑定控件
        /// </summary>
        public object BindControlLocationY { get; set; }
        /// <summary>
        /// 宽绑定控件
        /// </summary>
        public object BindControlItemWidth { get; set; }
        /// <summary>
        /// 高绑定控件
        /// </summary>
        public object BindControlItemHeight { get; set; }
    }
           

3、MyCanvas自定义控件的封装

新建自定义控件MyCanvas,添加MouseLeftButtonDown,MouseLeftButtonUp,MouseMove事件,xaml窗体代码:

<Canvas x:Class="MakeGif.MyCanvas"
        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" 
        xmlns:local="clr-namespace:MakeGif"
        mc:Ignorable="d" 
        Background="White" Width="840" Height="472" ClipToBounds="True"
        MouseLeftButtonDown="Canvas_MouseLeftButtonDown" MouseLeftButtonUp="Canvas_MouseLeftButtonUp" MouseMove="Canvas_MouseMove">
</Canvas>
           

其交互逻辑与博文WPF中GDI+图形图像的绘制:(八)位置坐标和宽高与控件绑定展示中一致,这里对其做了功能完善与封装   给出源码:

/// <summary>
    /// MyCanvas.xaml 的交互逻辑
    /// </summary>
    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 提供给外部的调用方法
        /// <summary>
        /// 展示素材
        /// </summary>
        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);
        }
        /// <summary>
        /// 清除底图
        /// </summary>
        public void ClearBackground()
        {
            foreach (var item in this.Children)
            {
                MyImage img = item as MyImage;
                if (img != null && !img.IsCanClick)
                {
                    this.Children.Remove(img);
                    return;
                } 
            }
        }
        /// <summary>
        /// 清除所有元素
        /// </summary>
        public void ClearFrameItem()
        {
            this.Children.Clear();
        }
        /// <summary>
        /// 改变X坐标
        /// </summary>
        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);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 改变Y坐标
        /// </summary>
        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);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 改变宽
        /// </summary>
        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);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 改变高
        /// </summary>
        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

        /// <summary>
        /// 鼠标按下
        /// </summary>
        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();
            }
        }
        /// <summary>
        /// 鼠标抬起
        /// </summary>
        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;
            }
        }
        /// <summary>
        /// 鼠标移动
        /// </summary>
        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;
        }
        /// <summary>
        /// 移动改变坐标或大小
        /// </summary>
        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)
            {
            }
        }
        /// <summary>
		/// 移动对象
		/// </summary>
		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);
            }
        }
        /// <summary>
        /// 左上角拖动
        /// </summary>
        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);
            }
        }
        /// <summary>
        /// 右上角拖动
        /// </summary>
        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);
            }
        }
        /// <summary>
        /// 左下角拖动
        /// </summary>
        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);
            }
        }
        /// <summary>
        /// 右下角拖动
        /// </summary>
        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);
            }
        }
        /// <summary>
        /// 设置其他为未选择状态
        /// </summary>
        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();
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 展示X坐标
        /// </summary>
        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);
                }
            }
        }
        /// <summary>
        /// 展示Y坐标
        /// </summary>
        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);
                }
                    
            }
        }
        /// <summary>
        /// 展示img宽
        /// </summary>
        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);
                }
            }
        }
        /// <summary>
        /// 展示img高
        /// </summary>
        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)

继续阅读