分类:
2010-09-16 14:50:53
程序运行时,当鼠标指针靠近窗口中心程度不同,客户区的背景颜色也不同。
WPF的颜色被封装成Color结构,定义在System.Windows.Media命名空间中;和一般的图形环境一样,Color结构使用红、绿、蓝三原色来表达颜色。这三种原色分别被简称为R、G、B;用这三种原色定义出来的三维空间,就是RGB颜色空间。
Color结构包含名为R、G、B的三个可读写属性,它们的类型都是byte。这三种属性的值范围从0到255。当这三个Property皆为0时就是黑色,当这三个Property皆为255时就是白色。
如下图,假设绿色矩形区域为屏幕窗口,点ptMouse(鼠标指针)为M点, 点ptCenter(中心)为O点,向量vectMouse 对应图中OM,角度angle为角MOA,向量vectEllipse 对应图中OM'。显然,向量OM'的长度大于等于向量OM的长,对应vectEllipse.Length>=vectMouse.Length ,当鼠标在屏幕边界时,OM=OM',byLevel =255*0,clr.R = clr.G = clr.B =0,屏幕为黑色;当鼠标在屏幕中心时,OM长为0,byLevel =255*1,clr.R = clr.G = clr.B =255,屏幕显示为白色。
只要鼠标在程序客户区,OnMouseMove方法会被持续调用。
每次只要brush一有改变,客户区域就会被重绘,这些都是幕后进行的。这里之所以会有动态的瓜,是因为Brush类继承自Freezable类,而Freezable类实现了一个名为Change的事件,Brush对象只要一有改变,这个事件就会被触发,背景就会被重画。
第02个小程序:遍历画笔(FlipThroughTheBrushes.cs)
GetProperties()函数用于返回对象数组,参数是限制Brushes公开和静态的属性。其实这里可以不需要这样的限制,因为Brushes的属性本来全部都是public和static。
props[index].Name返回第index个属性的名称;props[index].GetValue(null, null)返回实际的SolidColorBrush对象,第一个参数是属性所在的对象,因为Brushes是一个静态属性,没有对应的对象,传入null;第二个参数只有在属性是索引器是才有必要。
第03个小程序:渐变画笔(GradiateTheBrush.cs)
渐变画刷的实现
这里的表面被视为一个单位宽,一个单位高。表面的左上角是(0,0),右下角是(1,1)。
brush有个SpreadMethod属性,其默认值是GradientSpreadMethod.Pad,表示超出设定区域部分延续之前的颜色;另一个值GradientSpreadMethod.Reflect,表示按相向方向重复渐变;还有一个值GradientSpreadMethod.Repeat,表示按原始方向重复渐变。
修改LinearGradientBrush brush =……代码如下:
当SpreadMethod属性取不同值时,效果分别如下
第04个小程序:调整(设置)渐变参数(AdjustTheGradient.cs)
本程序实现的渐变方式如下图所示。假设绿色矩形区域为窗口区域,O点相当于中心ptCenter,对角线BD相当于向量vectDiag ,线MN对应于向量vectPerp ,width * height / vectDiag.Length的值等于MO或ON,M、N点对应brush.StartPoint 、brush.EndPoint 。AM、BD、NC都是等色线。
第05个小程序:水平彩虹(FollowTheRainbow.cs)
LinearGradientBrush渐变的颜色可以限定更多。下面水平渐变画彩虹的7种颜色。
GradientStops属性是GradientStopCollection类型,这是GradientStop对象的集合。
GradientStop(Color color, Double offset),offset值范围在0和1之间,是StartPoint和EndPoint的相对距离。
效果图:
第06个小程序:圆形彩虹(CircleTheRainbow.cs)
由客户中心向外画彩虹的7种颜色。
RadialGradientBrush的许多属性都已经具备实用的默认值。基中三个属性用来定义一个椭圆:Center是Point类型,定义为(0.5,0.5),即画刷涵盖区域中心点(还有个GradientOrigin,和Center一样)。RadiusX和RadiusY的属性为double类型,分别代表椭圆的水平和垂直轴半径,默认值是0.5,所以无论是横向还是纵向,椭圆都达到了当前画刷作用区域的边界。
在椭圆以外的区域(屏幕窗口的四个角落),将继续使用紫色,因为SpreadMethod的默认值是Fill。
本程序效果:
将以上代码作下修改(CircleTheRainbow.cs):
运行,这回按下空格键时,会看到各椭圆色圈从中心向外扩展,像石子引起的水波一样。
第07个小程序:点击渐变中心(ClickTheRadientCenter .cs)
GradientOrigin 是渐变开始的原点,在GradientOrigin 和椭圆圆周之间,就是发生渐变的地方。如果GradientOrigin 等于Center(默认如此),那么渐变会从椭圆圆心到椭圆圆周之间扩散。如果GradientOrigin 和Center之间有一段距离,那么在GradientOrigin 和最接近的椭圆圆周之间,渐变的颜色变化会比较剧烈,相反方向的颜色变化就比较缓和。
本程序就是演示这两种效果。鼠标左击时,GradientOrigin 等于Center,即使它们的值(位置)变了,结果依然是从椭圆中心到边界的渐变;但当鼠标右击时,GradientOrigin 不等于Center,只有GradientOrigin改变,则出现挤压或拉伸的状态。
效果如下:
第08个小程序:旋转渐变原点(RotateTheGradientOrigin .cs)
程序中添加了个记时器,效果做成了动画。
在.NET中,至少有4个记时器类型,其中3个都叫做Timer。System.Threading和System.Timers内的Timer类,在我们这个例子中并不能被使用,因为这些timer事件发生在不同的线程中,而Freezable对象只能被(创建它的)同一个线程所改变,而不能被其他线程改变。System.Windows.Forms内的Timer类型封装了标准的Windows操作系统计时器,但是使用它的话,还需要在工程中加入对System.Windows.Forms.dll组件的引用。
在这里,让事件发生在WPF程序的主线程中,System.Windows.Threading命名空间的DispatcherTimer类是最适合的。
效果截图:
Windows还有个Brush属性叫BordBrush,可以在客户的周围绘制一个边框。
在上面这个程序的构造函数中添加如下代码
效果如下
Thickness( double left, double top, double right, double bottom)里的几个参数分别表示边框左、上、右、下与客户区距离。它的另一个形式Thickness(
边框也可以使用渐变画刷,如将BorderBrush定义修改如下:
程序运行效果如下:
由图可看出,红色在边框左上角,绿色在边框右下角,不过并不干涉客户区其它地方。其实即使BoderBrush和Background都具有相同的渐变画刷,两者也不会彼此交融