上一节已经完成了功能需求和界面布局,这一节就说明一下编码。
本文分两部分:
(一)界面布局及数据初始化
(二)编码实现
1、 既然要求支持批量处理,那么一次就应该允许选择多个文件,在上一节的最后已经说明了一次选择多个文件,OpenFileDialog在返回的时候通过FileNames得到的是一个数组,所以要进行简单的转换成用分号(;)分隔的字符串,以便填入文本框中。
1 sorImage =null;
2 System.Windows.Forms.OpenFileDialog ofd =new System.Windows.Forms.OpenFileDialog();
3 ofd.Multiselect =true;
4 ofd.Filter ="图片文件(*.jpg *.gif *.png)|*.jpg;*.gif;*.png|All Files (*.*)|*.*";
5 if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
6 {
7 sorImage = ofd.FileNames;
8 }
9 else
10 sorImage =null;
11 if (sorImage !=null)
12 {
13 StringBuilder sb =new StringBuilder();
14 foreach (string item in sorImage)
15 {
16 sb.Append(item +";");
17 }
18 this.txtSource.Text = sb.ToString();
19 this.ucProgressBar1.Total = sorImage.Length;
20 this.ucProgressBar1.Value =0;
21 this.spnlView.Children.Clear();
22 }

同时,为了方便处理过程中的遍历,使用了Queue保存已经选择的图片文件,这样每次取出来个文件来处理就行了,直到Queue中不再有元素。

1 Queue<string> queue =new Queue<string>();
2、 在处理过程中,有一个动画处理每一张要处理的图片,这张图片初始的时候是铺满整个窗体,并且是完全透明,然后随着动画的进行,透明度逐渐增加到1,并且伴随着其他效果。整个动画使用了一个Storyboard和四个DoubleAnimation,分别为:
1 Storyboard sbSize =new Storyboard();
privatevoid InitStoryboard()
{
#region 大小
//宽
DoubleAnimation daWidth =new DoubleAnimation()
{
From =1,
To =0,
Duration =new Duration(TimeSpan.FromSeconds(1)),
FillBehavior = FillBehavior.Stop
};
sbSize.Children.Add(daWidth);
Storyboard.SetTarget(daWidth, this.imgMain);
Storyboard.SetTargetProperty(daWidth, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"));
//高
DoubleAnimation daHeight =new DoubleAnimation()
{
From =1,
To =0,
Duration =new Duration(TimeSpan.FromSeconds(1)),
FillBehavior = FillBehavior.Stop
};
sbSize.Children.Add(daHeight);
Storyboard.SetTarget(daHeight, this.imgMain);
Storyboard.SetTargetProperty(daHeight, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"));
#endregion
#region 移动
//移动
DoubleAnimation daTop =new DoubleAnimation()
{
To =280,
Duration =new Duration(TimeSpan.FromSeconds(1)),
FillBehavior = FillBehavior.Stop
};
sbSize.Children.Add(daTop);
Storyboard.SetTarget(daTop, this.imgMain);
Storyboard.SetTargetProperty(daTop, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[2].(TranslateTransform.Y)"));
#endregion
#region 透明度
DoubleAnimation daOpacity =new DoubleAnimation()
{
From =0,
To =1,
Duration =new Duration(TimeSpan.FromSeconds(1)),
FillBehavior = FillBehavior.Stop
};
sbSize.Children.Add(daOpacity);
Storyboard.SetTarget(daOpacity, this.imgMain);
Storyboard.SetTargetProperty(daOpacity, new PropertyPath(Image.OpacityProperty));
#endregion
}
这样形成动画效果叠加,展示了一个从无到有,从大到小,从上到下的渐变过程。

3、 点击启动后,先检查必要的参数及选项输入,把选中的文件一个一个保存的Queue中。接着就是开始启动动画了。
1 queue.Clear();
2 foreach (string item in sorImage)
3 {
4 queue.Enqueue(item);
5 }
6
7  this.sbSize.Begin();

4、 动画执行完成后,进行图片切割,然后把把切割后的缩略图加载到窗体下方的列表中。为了显示效果,在图片列表中缩略图上做了一些效果,鼠标移上/移出,点击等。
1 void Do(object obj)
2 {
3 DoParameter para = obj as DoParameter;
4 if (File.Exists(currentImgUrl))
5 {
6 System.Windows.Forms.Application.DoEvents();
7 this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new EventHandler((o1, e1) =>
8 {
9 BitmapImage im = ImageHelper.Thumbnail(currentImgUrl,
10 System.IO.Path.Combine(para.DestinationPath, System.IO.Path.GetFileName(currentImgUrl)),
11 para.IsRename,
12 para.Width,
13 para.Height,
14 para.Mode,
15 para.Interpolation,
16 para.Smoothing,
17 para.Watermark);
18
19 this.ucProgressBar1.Value +=1;
20
21 Image imgList =new Image();
22 imgList.SetValue(Image.SourceProperty, im);
23 imgList.Height =90;
24 imgList.Width =120;// (4.0 / 3) * 90;
25   imgList.Margin =new Thickness(5, 0, 5, 0);
26 DropShadowEffect d =new DropShadowEffect();
27 d.BlurRadius =3;
28 d.ShadowDepth =4;
29 d.Color = Color.FromRgb(218, 214, 114);
30 imgList.Effect = d;
31 imgList.MouseEnter +=new System.Windows.Input.MouseEventHandler(imgList_MouseEnter);
32 imgList.MouseLeave +=new System.Windows.Input.MouseEventHandler(imgList_MouseLeave);
33 this.spnlView.Children.Add(imgList);
34 im =null;
35 }), null, null);
36 currentImg =null;
37 }
38 }
39
40 void imgList_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
41 {
42 Image img = (Image)sender;
43 DropShadowEffect d =new DropShadowEffect();
44 d.BlurRadius =3;
45 d.ShadowDepth =4;
46 d.Color = Color.FromRgb(218, 214, 114);
47 img.Effect = d;
48 }
49
50 void imgList_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
51 {
52 Image img = (Image)sender;
53 DropShadowEffect d =new DropShadowEffect();
54 d.BlurRadius =3;
55 d.ShadowDepth =4;
56 d.Color = Color.FromRgb(255, 0, 0);
57 img.Effect = d;
58 this.imgBG.ImageSource = img.Source;
59 }
5、要注意一点,当鼠标离开缩略图列表区域时,还得把窗体背景重新设置为默认图片。
1 privatevoid scrolls_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
2 {
3 if (this.imgBG.ImageSource != bgImg)
4 this.imgBG.ImageSource = bgImg;
5 }
6、 一图片处理完成后,紧接着检查Queue中是否还有元素,如果有则继续执行动画,如此循环4和5两步,否则退出此次执行命令。
View Code

1 void InitImageMain()
2 {
3 if (queue.Count >0&& isRunning)
4 {
5 currentImgUrl = queue.Dequeue();
6 currentImg = ImageHelper.CreateBitmapImage(currentImgUrl); ;
7 this.imgMain.Source = currentImg;
8 currentImg =null;
9
10 this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new EventHandler((o1, e1) =>
11 {
12 sbSize.Begin();
13 }), null, null);
14 }
15 else
16 {
17 this.imgMain.Source =null;
18 isRunning =false;
19 this.btnStart.IsEnabled =true;
20 }
21 }


7、另外一点,使用的那个进度条是自定义的用户控件,其实是一个简单组合,就是在一个ProgressBar上放一个TextBlock即可,这样方便控制,既展示了进度,也显示了提示信息。
1 <Grid>
2 <ProgressBar x:Name="pressBar" Margin="0,0,0,0" Opacity="0.7"/>
3 <TextBlock x:Name="txtValue" Margin="0,0,0,0" TextWrapping="Wrap" Text="0/0" TextAlignment="Center" FontSize="16"/>
4 </Grid>
View Code

1 publicpartialclass UcProgressBar : UserControl
2 {
3 public UcProgressBar()
4 {
5 InitializeComponent();
6 }
7
8 int _total =100;
9
10 publicint Total
11 {
12 get { return _total; }
13 set
14 {
15 if (value<0)
16 {
17 value =0;
18 }
19 _total = value;
20 this.pressBar.Maximum =this._total;
21 this.txtValue.Text =string.Format("{0}/{1}", _value, _total);
22 }
23 }
24
25 int _value =0;
26
27 publicint Value
28 {
29 get { return _value; }
30 set
31 {
32 if (value<0)
33 {
34 value =0;
35 }
36 _value = value;
37 this.pressBar.Value = value;
38 this.txtValue.Text =string.Format("{0}/{1}", _value, _total);
39 }
40 }
41 }

总结:小工具的整个实现并不复杂,只是把几个常用的元素融合到了一起:动画、图片切割、自定义用户控件。
试用下载

转载于:https://www.cnblogs.com/solan/archive/2011/04/11/2012050.html

WPF纯手工两步打造图片切割工具(二)相关推荐

  1. WPF纯手工两步打造图片切割工具(一)

    一.功能说明 1.四种图片切割方式:缩放:指定宽高(可能变形).缩放:指定宽(高按比例).缩放:指定高(宽按比例).裁减:指定宽高. 2.批量图片切割. 3.目标存储区同名文件处理:直接覆盖.重新命名 ...

  2. 《安富莱嵌入式周报》第282期:CMSIS-DSP手册引入计算图,树莓派单片机RP2040超频到1GHz,COBS字节编码算法,纯手工为PS1打造全新亚克力外壳

    往期周报汇总地址:嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - P ...

  3. ShoeBox一个超级好用的图片切割工具

    ShoeBox一个超级好用的图片切割工具 两款图片切割工具 ShoeBox:http://renderhjs.net/shoebox/ BigShear:https://www.fancynode.c ...

  4. 一个非常好用的图片切割工具(c# winform开发)

    本人业余时间开发了一个图片切割工具,非常好用,也很灵活! 特别对大型图片切割,更能体现出该软件的优势! 功能说明 可以设定切割的高度和宽度.切割线可以上下拖动,可以增加一个切割区域,可设定某个区域不参 ...

  5. [工具集]等比序列帧图片切割工具

    快速对图片进行等比裁剪,导出分类好的文件夹. 工具基于Qt编写,因为代码不知道放哪了,暂不支持批处理操作 效果: 下载: https://pan.baidu.com/s/1gvGvLVPABNuZ1t ...

  6. C#图片处理类(颜色透明化,图片切割,图片合并,图片旋转等)(转)

                              目录 1.背景透明化 2.指定颜色透明化 3.指定颜色替换成另一种颜色 4.图片按比例缩放 5.图片旋转 6.图片更改透明度 7.图片添加文字 8. ...

  7. 消防管件做的机器人图片_报废消防器材变身“机器人” 由消防官兵纯手工打造(图)...

    原标题:报废消防器材变身"机器人" 由消防官兵纯手工打造(图) 由报废的消防零配件组成的机器人模型. 厦门网讯 (厦门日报记者林路然通讯员阙凤芳曾德猛)远看好似变形金刚,凑近还会说 ...

  8. 19岁「天才少年」自制CPU!1200个晶体管,纯手工打造

    ‍ 大家好,我是张巧龙,在推特上看到一个19岁的博主,耗时整整3年,纯手工自制1200个晶体管的CPU. 这位叫做 Sam Zeloof 的美国大学生,最终打造出1200个晶体管的CPU! 在10微米 ...

  9. ☆☆☆ 纯手工打造个性化的 GhostXP 系统 ☆☆☆

    既然是用纯手工来制作万能克隆系统,那么能用手工做到的事情就尽量用手工来做,尽量少用自动化的功能去实现,这样不仅能够详细的了解和学习系统封装的全过程,而且还能感受到封装系统带来的无穷乐趣. 大部分内容参 ...

最新文章

  1. 一看就会的20个“非常有用”的python小技巧,你一定要试试
  2. 【转发】centos7支持ntfs
  3. bootstrap中modal弹出框的使用
  4. java读取rvt文件数据_Revit二次开发之隐藏API 独立进程读取rvt文件
  5. 1900页Python系列PPT分享六:面向对象程序设计(86页)
  6. C++ template —— 模板中的名称(三)
  7. 严重BS骗样本的骗子
  8. 非常好的Oracle基础教程
  9. 自然语言表示简史(BERT/ELMO/Word2vec/LDA/Bow/Ohehot,词向量、句向量、优缺点、应用与解决的问题)
  10. Android 退出登录实现
  11. 集线器与交换机的区别
  12. java实现自动拨打电话语音提示
  13. iPhone支持杜比的机型
  14. 功能测试--如何对时间(年月日)进行测试
  15. reids 5.0.4 cluster集群模式部署实操。
  16. 阿里的面试官都喜欢问哪些问题?
  17. 当神经网络的模型还不如决策树的效果好
  18. Webstorm的一些常用快捷键
  19. 《人工智能与大数据技术导论》适合用来深度了解AI和BD技术
  20. 微信小程序 网上药店管理系统Android hbuilderx App毕业设计

热门文章

  1. python创建新进程_Python os.fork()方法:创建新进程
  2. DenseNet论文笔记
  3. 最详细的YOLOv3论文笔记
  4. jQuery 中$('.classname').on('click',function(){});与$(document).on('click','.classname',function(){});
  5. 接口测试基础一--HTTP请求
  6. MsSql 生成数据文档
  7. Strust2初之体验
  8. 站在Java的角度看LinkedList
  9. node.js通过edge访问.net动态链接库
  10. ASP.NET MVC+EF框架+EasyUI实现权限管理系列(18)-过滤器的使用和批量删除数据(伪删除和直接删除)...