现在如果想打造一款专业的App,UI的设计和操作的简便性相当重要。UI设计可以借助Photoshop或者AI等设计工具,之前了解到WPF设计工具Expression Blend可以直接导入PSD文件或者AI设计文件(当然不是全部特征支持),最近研究了一下,也费了一番周折,好在最后实现了预期的效果。下面将step by step用示例说明如何先用PS构建一个矢量图形模板,然后用Expression Blend导入PSD文件,并获取PATH的Data值,为打造一款炫酷的个性进度条控件构建美观UI。

1、打开Photoshop,新建一个空白图层,点选PS的图案图章工具:

2、选择画笔,选用喜欢的笔刷(可以到网站上下载免费的笔刷),如下图:

在合适位置点击后,如下图所示。

3、按住CTRL,选中图层,切换到路径面板,点击 【从选取创建工作路径】 按钮,如下图:

注意上图的红框按钮,就是【从选取创建工作路径】,点击后出现下图:

4、这是最关键的一步,创建矢量蒙板,切换到图层面板,点选【钢笔】工具,在图形上右键菜单中选择【创建矢量蒙板】项,如下图所示:

然后PS中可以看到下图的效果,说明创建成功。

保存PS文件为进度条.PSD文件待用。

5、打开Expression Blend 4新建一个WPF项目,然后导入PSD文件,如下图:

导入成功后,可以复制该图形的clip数据,这就是WPF中PATH所需要的Data值。

下面来创建一个炫酷的WPF进度条控件。

6、在VS2010中重新打开该项目,并添加一个WPF自定义控件库,如下图:

17 编写控件UI和后台代码,如下所示:

 <ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfCustomProgressControl"> <Style TargetType="{x:Type local:CustomProgressControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomProgressControl}">
<Grid x:Name="PART_container"
Background="{TemplateBinding Background}"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}">
<Path x:Name="PART_foreground_P"
Visibility="Collapsed"
Stretch="Fill"
Stroke="Transparent"
Fill="{TemplateBinding Foreground}"
StrokeThickness="2"
Data="F1M56,33C58,33 60,33 62,33 61.667,33.667 61.333,34.333 61,35 57.794,34.859 53.856,36.079 56,33z M49,24C54.364,24.735 53.554,24.821 56,28 53.807,30.696 55.287,29.902 51,31 50,30 49,29 48,28 48.333,26.667 48.667,25.333 49,24z M62,22C63.666,22.333 65.333,22.667 67,23 66.333,27.571 65.935,27.376 64,30 63,29.333 62,28.667 61,28 61,27.667 61,27.333 61,27 61.333,25.333 61.667,23.666 62,22z M46,15C46.667,15 47.333,15 48,15 47.333,17.333 46.667,19.667 46,22 45.333,22 44.667,22 44,22 44.667,19.667 45.333,17.333 46,15z M63,13C64.923,14.392 63.599,13.101 65,15 64.333,14.333 63.667,13.667 63,13z M55,12C56.666,12.667 58.333,13.333 60,14 60,15.333 60,16.667 60,18 59.333,18 58.667,18 58,18 54.722,21.928 52.838,16.561 52,14 53,13.333 54,12.667 55,12z M128,1C128.667,1 129.333,1 130,1 128.882,10.058 122.793,12.326 122,23 126.364,22.028 126.876,21.206 131,22 130,23.333 129,24.667 128,26 110.659,32.752 112.704,45.252 103,59 95.769,69.245 82.761,82.131 72,89 72.621,101.092 82.373,112.463 90,118 90.333,118 90.667,118 91,118 93.274,107.421 107.464,106.386 104,92 101.667,87.667 99.333,83.333 97,79 98,78 99,77 100,76 122.812,77.152 112.786,100.488 115,114 116.666,115.666 118.333,117.333 120,119 127.359,142.373 118.776,160.626 106,168 110.337,176.877 114.918,188.188 121,197 127.441,206.332 140.794,210.508 148,220 146.506,223.067 146.885,223.215 144,225 113.08,236.802 62.376,138.34 36,147 34.077,151.751 32.347,152.761 28,155 17.556,150.255 9.333,141.565 9,127 13.999,120.001 19,112.999 24,106 22.667,102.667 21.333,99.333 20,96 7.555,96.019 4.392,90.889 1,82 1.465,74.486 3.768,68.82 9,66 19.848,56.341 31.922,71.946 38,77 37.406,83.299 36.792,87.413 39,92 41.333,89.667 43.667,87.333 46,85 81.009,67.269 105.228,31.536 128,1z" /> <Rectangle x:Name="PART_mask"
Fill="{TemplateBinding Background}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" /> <Path x:Name="PART_outline_P"
Visibility="Collapsed"
Stretch="Fill"
Stroke="{TemplateBinding BorderBrush}"
Fill="Transparent"
StrokeThickness="2"
Data="F1M56,33C58,33 60,33 62,33 61.667,33.667 61.333,34.333 61,35 57.794,34.859 53.856,36.079 56,33z M49,24C54.364,24.735 53.554,24.821 56,28 53.807,30.696 55.287,29.902 51,31 50,30 49,29 48,28 48.333,26.667 48.667,25.333 49,24z M62,22C63.666,22.333 65.333,22.667 67,23 66.333,27.571 65.935,27.376 64,30 63,29.333 62,28.667 61,28 61,27.667 61,27.333 61,27 61.333,25.333 61.667,23.666 62,22z M46,15C46.667,15 47.333,15 48,15 47.333,17.333 46.667,19.667 46,22 45.333,22 44.667,22 44,22 44.667,19.667 45.333,17.333 46,15z M63,13C64.923,14.392 63.599,13.101 65,15 64.333,14.333 63.667,13.667 63,13z M55,12C56.666,12.667 58.333,13.333 60,14 60,15.333 60,16.667 60,18 59.333,18 58.667,18 58,18 54.722,21.928 52.838,16.561 52,14 53,13.333 54,12.667 55,12z M128,1C128.667,1 129.333,1 130,1 128.882,10.058 122.793,12.326 122,23 126.364,22.028 126.876,21.206 131,22 130,23.333 129,24.667 128,26 110.659,32.752 112.704,45.252 103,59 95.769,69.245 82.761,82.131 72,89 72.621,101.092 82.373,112.463 90,118 90.333,118 90.667,118 91,118 93.274,107.421 107.464,106.386 104,92 101.667,87.667 99.333,83.333 97,79 98,78 99,77 100,76 122.812,77.152 112.786,100.488 115,114 116.666,115.666 118.333,117.333 120,119 127.359,142.373 118.776,160.626 106,168 110.337,176.877 114.918,188.188 121,197 127.441,206.332 140.794,210.508 148,220 146.506,223.067 146.885,223.215 144,225 113.08,236.802 62.376,138.34 36,147 34.077,151.751 32.347,152.761 28,155 17.556,150.255 9.333,141.565 9,127 13.999,120.001 19,112.999 24,106 22.667,102.667 21.333,99.333 20,96 7.555,96.019 4.392,90.889 1,82 1.465,74.486 3.768,68.82 9,66 19.848,56.341 31.922,71.946 38,77 37.406,83.299 36.792,87.413 39,92 41.333,89.667 43.667,87.333 46,85 81.009,67.269 105.228,31.536 128,1z" /> <TextBlock x:Name="PART_percentage_text"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontSize="16"
FontWeight="ExtraBlack"
Foreground="{TemplateBinding TextForeground}"/> </Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> </ResourceDictionary>
 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 WpfCustomProgressControl
{ [TemplatePart(Name = "PART_mask", Type = typeof(Rectangle))]
[TemplatePart(Name = "PART_container", Type = typeof(Grid))]
[TemplatePart(Name = "PART_percentage_text", Type = typeof(TextBlock))]
[TemplatePart(Name = "PART_foreground_P", Type = typeof(Path))]
[TemplatePart(Name = "PART_outline_P", Type = typeof(Path))] public class CustomProgressControl : ProgressBar
{
static CustomProgressControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomProgressControl), new FrameworkPropertyMetadata(typeof(CustomProgressControl))); } Rectangle mask;
Grid container;
TextBlock percentageText;
Path foreground_P;
Path outline_P; #region TextForeground 文本
public SolidColorBrush TextForeground
{
get { return (SolidColorBrush)GetValue(TextForegroundProperty); }
set { SetValue(TextForegroundProperty, value); }
} public static readonly DependencyProperty TextForegroundProperty =
DependencyProperty.Register("TextForeground", typeof(SolidColorBrush),
typeof(CustomProgressControl),
new FrameworkPropertyMetadata(new SolidColorBrush(Colors.DarkGray)));
#endregion public override void OnApplyTemplate()
{
base.OnApplyTemplate(); foreground_P = this.Template.FindName("PART_foreground_P", this) as Path;
outline_P = this.Template.FindName("PART_outline_P", this) as Path;
mask = this.Template.FindName("PART_mask", this) as Rectangle;
container = this.Template.FindName("PART_container", this) as Grid;
percentageText = this.Template.FindName("PART_percentage_text", this) as TextBlock;
if (foreground_P != null)
{
foreground_P.Visibility = Visibility.Visible;
outline_P.Visibility = Visibility.Visible;
}
Width = double.IsNaN(Width) ? : Width;
Height = double.IsNaN(Height) ? : Height; Minimum = double.IsNaN(Minimum) ? : Minimum;
Maximum = double.IsNaN(Maximum) ? : Maximum; if (mask != null)
{
var percentageValue = Value / Maximum;
var awayMargin = percentageValue * Height;
var percentageString = string.Empty; if (percentageValue > )
percentageString = (percentageValue * ).ToString("##");
else if (percentageValue == )
percentageString = ""; percentageText.Text = string.Format("{0}%", string.IsNullOrEmpty(percentageString) ? "" : percentageString); mask.Margin = new Thickness(, , , awayMargin);
} container.Clip = new RectangleGeometry
{
Rect = new Rect(, , Width, Height)
}; mask.Width = Width;
mask.Height = Height;
} protected override void OnValueChanged(double oldValue, double newValue)
{
base.OnValueChanged(oldValue, newValue); if (Value < Minimum)
{
Value = Minimum;
} if (Value > Maximum)
{
Value = Maximum;
} if (mask != null)
{
var percentageValue = Value / Maximum;
var awayMargin = percentageValue * Height;
var percentageString = string.Empty; if (percentageValue > )
percentageString = (percentageValue * ).ToString("##");
else if (percentageValue == )
percentageString = ""; percentageText.Text = string.Format("{0}%", string.IsNullOrEmpty(percentageString) ? "" : percentageString);
//蒙板来变更进度
mask.Margin = new Thickness(, , , awayMargin); }
}
}
}

18 在WpfPSDemo的主界面上拖入控件,并定制属性,代码如下:

 <Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ed="http://schemas.microsoft.com/expression/2010/drawing"
x:Class="WpfPSDemo.MainWindow"
x:Name="Window" BorderThickness="0"
Title="MainWindow"
Width="430" Height="480" xmlns:my="clr-namespace:WpfCustomProgressControl;assembly=WpfCustomProgressControl">
<my:CustomProgressControl Name="customProgressControl1" Width="200" Height="200" Value="50" Background="Yellow" Foreground="Red" BorderBrush="red" />
</Window>
 using System;
using System.Collections.Generic;
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.Shapes;
using System.Threading;
namespace WpfPSDemo
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
Thread timeThread;
int i = ;
public MainWindow()
{
this.InitializeComponent();
this.customProgressControl1.Value = ;
this.Background = Brushes.Yellow;
timeThread = new Thread(new ThreadStart(DispatcherThread));
timeThread.Start(); }
public void DispatcherThread()
{
//可以通过循环条件来控制UI的更新
while (true)
{
///线程方法委托(无参方法)
this.customProgressControl1.Dispatcher.BeginInvoke(new Action(UpdateTime));
Thread.Sleep();
}
} private void UpdateTime()
{ if (i < )
{
i++;
this.customProgressControl1.Value = i;
}
else
{
timeThread.Abort();
} }
}
}

运行代码,效果如下:

Photoshop和WPF双剑配合,打造炫酷个性的进度条控件的更多相关文章

  1. 示例:WPF中Slider控件封装的缓冲播放进度条控件

    原文:示例:WPF中Slider控件封装的缓冲播放进度条控件 一.目的:模仿播放器播放进度条,支持缓冲任务功能 二.进度: 实现类似播放器中带缓存的播放样式(播放区域.缓冲区域.全部区域等样式) 实现 ...

  2. WPF自定义控件第一 - 进度条控件

    本文主要针对WPF新手,高手可以直接忽略,更希望高手们能给出一些更好的实现思路. 前期一个小任务需要实现一个类似含步骤进度条的控件.虽然对于XAML的了解还不是足够深入,还是摸索着做了一个.这篇文章介 ...

  3. iOSQuartz2D-02-绘制炫酷的下载进度条

    效果图 实现思路 要实现绘图,通常需要自定义一个UIView的子类,重写父类的- (void)drawRect:(CGRect)rect方法,在该方法中实现绘图操作 若想显示下载进度,只需要实例化自定 ...

  4. Android自定义View(RollWeekView-炫酷的星期日期选择控件)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/53420889 本文出自:[openXu的博客] 目录: 1分析 2定义控件布局 3定义Cus ...

  5. Android ViewPager 打造炫酷欢迎页

    Android ViewPager 打造炫酷欢迎页 ViewPager是Android扩展v4包中的类,这个类可以让用户切换当前的View.对于这个类的应用场景,稍加修改就可以应用到多个环境下.比如: ...

  6. Android 教你打造炫酷的ViewPagerIndicator 不仅仅是高仿MIUI

    1.概述 哈,今天给大家带来一个ViewPagerIndicator的制作,相信大家在做tabIndicator的时候,大多数人都用过 TabPageIndicator,并且很多知名APP都使用过这个 ...

  7. JParticles 2.0 发布,打造炫酷的粒子特效

    JParticles 2.0 发布,打造炫酷的粒子特效.不好意思哈,在这么繁花似锦的世界里,标题不得不取得吸引眼球一点哈,不然...还是不啰嗦了,我们进入正题吧 简单介绍一下 JParticles 2 ...

  8. C# WPF 低仿网易云音乐(PC)歌词控件

    原文:C# WPF 低仿网易云音乐(PC)歌词控件 提醒:本篇博客记录了修改的过程,废话比较多,需要项目源码和看演示效果的直接拉到文章最底部~ 网易云音乐获取歌词的api地址 http://music ...

  9. WPF加载Winform窗体时 报错:子控件不能为顶级窗体

    一.wpf项目中引用WindowsFormsIntegration和System.Windows.Forms 二.Form1.Designer.cs 的 partial class Form1 设置为 ...

随机推荐

  1. Lookup 组件异常

    Lookup组件有两个数据源,一个是上流组件的输出,一个是组件lookup的数据源,这个数据源是在Connection选项卡中进行配置.在开发package的过程中,我发现一个异常,当Lookup数据 ...

  2. codeforces Gargari and Permutations(DAG+BFS)

    /* 题意:求出多个全排列的lcs! 思路:因为是全排列,所以每一行的每一个数字都不会重复,所以如果有每一个全排列的数字 i 都在数字 j的前面,那么i, j建立一条有向边! 最后用bfs遍历整个图, ...

  3. SQL*Loader之CASE8

    CASE8 1. SQL脚本 [oracle@node3 ulcase]$ cat ulcase8.sql set termout off rem host write sys$output &quo ...

  4. 轻松自动化---selenium-webdriver(python) (十一)

    本节重点: 控制滚动条到底部 有时候我们需要控制页面滚动条上的滚动条,但滚动条并非页面上的元素,这个时候就需要借助js是来进行操作.一般用到操作滚动条的会两个场景: 注册时的法律条文需要阅读,判断用户 ...

  5. 使用 CSS3 动感的图片标题动画效果【附源码下载】

    在网站中,有很多地方会需要在图片上显示图片标题.使用 CSS3 过渡和变换可以实现动感的鼠标悬停显示效果.没有使用 JavaScript,所以只能在支持 CSS3 动画的现代浏览器中才能正常工作.您可 ...

  6. java类的初始化和对象的创建顺序

    学习java编程思想--类的初始化p146 类的加载顺序* 1加载器启动找到 xxx.class文件,通过extends关键字寻找基类,先加载基类* 2类初始化先初始化static成员变量和stati ...

  7. 安装logstash,elasticsearch,kibana三件套

    logstash,elasticsearch,kibana三件套 elk是指logstash,elasticsearch,kibana三件套,这三件套可以组成日志分析和监控工具 注意: 关于安装文档, ...

  8. 【原创】Kakfa metrics包源代码分析

    这个包主要是与Kafka度量相关的. 一.KafkaTimer.scala 对代码块的运行进行计时.仅提供一个方法: timer——在运行传入函数f的同时为期计时 二.KafkaMetricsConf ...

  9. WinForm 容器控件

    容器控件: 布局:2个属性:Anchor:锁定位置Dock:填充位置一般Dock是与容器控件配合使用 Panel:就是一个区域,类似于DIV,可以独立布局,还可以让其它控件及容器在它的内部再次布局 F ...

  10. bootstrap学习笔记系列4------bootstrap按钮

    按钮标签 在<a>,<button>或input元素上使用按钮class.但是为了避免跨浏览器的不一致性,建议使用<button>标签. <!DOCTYPE ...