WPF学习手记-03 Basic Brushse(一)
来源:互联网 发布:如何知道mysql的密码 编辑:程序博客网 时间:2024/05/16 17:51
Chapter 2 Basic Brushes
在上一章里我们看到Window的颜色是White,你可以通过控制面板来改变这个默认颜色,在WPF中颜色被定义为名为Color的结构体,该结构体位于System.Windows.Media namespace下(注意:这里的Color与System.Drawing下的Color是不同的, System.Drawing下的Color用于Windows Form Application,是基于GDI or GDI+的),WPF下的这个新的Color结构与原有Windows Form中的Color有什么不同呢?
先来说说相同的地方,你依然可以使用RGB值来定义Color的颜色,你也依然可以使用A来定义Color的透明度,ARGB依然是byte类型的,取值从0到255.
再来说说不同的地方,新的Color结构与原来的Color最大不同就是多了4个新的属性,叫做ScA,ScR,ScG,ScB,这四个属性的数据类型是float类型的, ScA,ScR,ScG,ScB与A,R,G,B是相互影响的,改变ScA,ScR,ScG,ScB的值同时也会改变A,R,G,B的值.
ScR,ScG,ScB与R,G,B之间并非一个线形的关系,它们之间的关系如下表:
scG
G
<= 0
0
0.1
89
0.2
124
0.3
149
0.4
170
0.5
188
0.6
203
0.7
218
0.8
231
0.9
243
>= 1.0
255
ScR,ScG,ScB与R,G,B之间有一样的关系.
阴极射线管所显示的光并非是线性的,光强I(light intensity)与显示器上的电压V(voltages)存在如下的关系:
I = Vγ
γ表示的值是代表显示器的特征和周围环境的光,而我们通常所使用的显示器该值的范围在2.2~2.5之间,而R,G,B采用的是值为2.2的转换(这里一大堆理论知识的描述,看的好头晕,什么人类感知光是非线性的,但近似是线性的@#$%... ...),总之,ScG与G之间存在下面的近似转换公式:
ScG≈(G/255)2.2
注意这个近似关系,当值很小的时候此公式越准确,而ScA与A之间存在更加简单的关系:
ScA = A/255
Sc-类型的Color的引入主要是为了解决WPF Application在不同的场合下能够拥有相同的表现而引入的;
你还可以使用以下的静态方法创建Color结构:
Color.FromRgb(r,g,b);
Color.FromArgb(a,r,g,b);
Color.FromScRgb(a,r,g,b);
System.Windows.Media下同时还包含一个名为Colors的类,里面定义了141个只读属性比如AliceBlue,AntiqueWhite,Yellow,Lime等. 这些颜色在Web程序上也是同样的.
这141个颜色的中有一个特殊的就是Transparent(透明),它与其它140个Color的不同在于Transparent的A为0,而其它Color的A为255;
介绍完了Color,这时让我们来设置一下Window的背景颜色,我尝试像Windows Form那样去设置Window的background:
win.Background = Colors.Blue;
报错了,因为Window对象的Background是一个Brush类型的属性.
Brush在WPF体系中的应用是如此的广泛,Brush本身是一个抽象类,Brush的类层次如下所示:
Object
DispatcherObject (abstract)
DependencyObject
Freezable (abstract)
Animatable (abstract)
Brush (abstract)
GradientBrush (abstract)
LinearGradientBrush
RadialGradientBrush
SolidColorBrush
TileBrush (abstract)
DrawingBrush
ImageBrush
VisualBrush
Brush同样位于System.Windows.Media namespace下,本章要介绍的是SolidColorBrush和GradientBrush下面的2个Brush.
SolidColorBrush是单色Brush,你可以用下面的代码为Window的Background赋值:
win.Background = new SolidColorBrush(Colors.Blue);
同Colors类似,System.Windows.Media下面同样有一个Brushes Class,该类中也包含了141个只读属性,这141个属性返回141个SolidColorBrush,贴段代码:
// VaryTheBackground.cs (c) 2006 by Charles Petzold
//--------------------------------------------------
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
namespace Petzold.VaryTheBackground
...{
public class VaryTheBackground : Window
...{
SolidColorBrush brush = new
SolidColorBrush(Colors.Black);
[STAThread]
public static void Main()
...{
Application app = new Application();
app.Run(new VaryTheBackground());
}
public VaryTheBackground()
...{
Title = "Vary the Background";
Width = 384;
Height = 384;
Background = brush;
}
protected override void OnMouseMove
(MouseEventArgs args)
...{
double width = ActualWidth
- 2 * SystemParameters
.ResizeFrameVerticalBorderWidth;
double height = ActualHeight
- 2 * SystemParameters
.ResizeFrameHorizontalBorderHeight
- SystemParameters.CaptionHeight;
Point ptMouse = args.GetPosition(this);
Point ptCenter = new Point(width / 2,
height / 2);
Vector vectMouse = ptMouse - ptCenter;
double angle = Math.Atan2(vectMouse.Y,
vectMouse.X);
Vector vectEllipse = new Vector(width
/ 2 * Math.Cos(angle),
height
/ 2 * Math.Sin(angle));
Byte byLevel = (byte)(255 * (1 - Math
.Min(1, vectMouse.Length /
vectEllipse.Length)));
Color clr = brush.Color;
clr.R = clr.G = clr.B = byLevel;
brush.Color = clr;
}
}
}
运行一下这段代码,很酷吧!现在把
SolidColorBrush brush = new SolidColorBrush(Colors.Black);
换成
SolidColorBrush brush = Brushes.Black;
竟然报错了
Cannot set a property on object '#FF000000' because it is in a read-only state.
原因稍后解释,首先对于上面的代码,你看到了很酷的效果,你会发现当你移动鼠标的时候Window一直在重绘,但其实这一切都发生在后台,这种动态响应的方式是由于Brush继承了Freezable抽象类,实现了该类的一个名为Changed的事件,这个事件在Brush发生任何改变时触发,这也是为什么Background一直会被重绘的原因.对于Animation以及WPF的其它一些特征Changed事件用相同的机制在后台发挥着作用.
现在来解释一下上面的错误.从Brushes返回的SolidColorBrush是一个frozen(被冻结)的Freezable对象,这就意味着它将不能再被改变,由于SolidColorBrush的Changed事件等都是从Freezable继承来的,如果Freezable对象的CanFreeze属性设置为true,你就可以调用Freeze方法得到一个被冻结的不能改变的对象,因为它不再需要监控任何改变.一个frozen(被冻结)的Freezable对象可以被其它线程共享(share),而一个unfrozen(未被冻结)的Freezable对象却不能.尽管我们无法为一个已经frozen(被冻结)的Freezable对象”解冻”,但我们可以从这个已经frozen(被冻结)的Freezable对象获得一个unfrozen(未被冻结)的Copy!
你现在可以把
SolidColorBrush brush = Brushes.Black;
换成
SolidColorBrush brush = Brushes.Black.Clone();
现在程序又可以正常工作了.在System.Window下面有一个SystemColors的类,该类下面定义了与系统相关的Color和Brush,这里的Brush也是frozen(被冻结)的,所以可以改变这个Brush
Brush brush = new SystemColorBrush(SystemColors.WindowColor);
但不可以改变这个Brush
Brush brush = SystemColors.WindowBrush;
- WPF学习手记-03 Basic Brushse(一)
- WPF学习手记-04 Basic Brushse(二)
- Hibernate学习手记(一)
- Hibernate学习手记(一)
- RoR学习手记(一)
- JMS学习手记<一>
- WPF学习手记-01 废话在前
- .NET学习手记之:WPF-布局
- .NET学习手记之:WPF--资源
- .NET学习手记之:WPF--线程
- .NET学习手记之:WPF--路由事件
- DirectDraw 学习手记(一)
- .Net学习手记(一)
- SSH2学习手记(一)
- java学习手记(一)
- C#学习手记(一)
- WPF学习笔记一
- WPF学习笔记(一)
- 程序员必看.........面试过程..经典.............
- 用 Spring MVC 轻松进行应用程序开发(图)
- Struts2文件的上传和下载
- 如何解决oracle死锁问题
- C#开发和使用中的23个技巧
- WPF学习手记-03 Basic Brushse(一)
- 理解MVC(转)
- 修改启动参数重置IBM WebSpere Application Developer 的工作区
- 无光驱无软驱安装系统
- Java编写的模拟ATM取款机程序
- Spring StrutsMVC 总体概述
- @ Control各属性说明(官网)
- SQL Server 索引结构及其使用(一)
- 缓冲区溢出原理浅析以及防护