本讲介绍了WPF中的基本形状,包括矩形、椭圆形、直线、折线、多边形、点划线等。还介绍四类画刷的使用。介绍了形状的旋转及移动等变化,元素的旋转及移动等。最后介绍了透明。
1.形状
WPF支持的形状有:Rectangle,Ellipse,Line,Polyline,Polygon,Path,这些都继承自Shape类,Shape类是抽象类不能执行任何工作,但他定义了少量的重要的属性。
- Fill:设置绘制形状表面(边框内的所有内容)的画刷对象
- Stroke:设置绘制形状边缘(边框)的画刷对象
- StrokeThickness:用设备无关单位设置边框的宽度。当绘制直线时,WPF在两边分割宽度。因此,10个单位宽的直线,会在绘制1个单位宽的直线所在位置的两侧占用5个单位的空间。如果直线的宽度为奇数,直线在两侧的宽度值就会是小数。例如,一条宽度为11个单位的直线,两侧会有5.5 单位的空间。对于这种情况,直线肯定不会和监视器上的显示像素对齐,即使使用 96dpi的分辨率也同样如此,从而最后直线的边缘会具有模糊的反锯齿效果。如果不喜欢,可使用SnapsToDevicePixels属性去掉该效果(正如本章后面12.1.10节“像素对齐”所述)
- StrokeStartLineGap和StrokeEndLineGap:决定直线开始端和结束端边缘的轮廓。这些属性只影响Line、Polyline 以及(在某些情况下)Path 形状。所有其他形状都是闭合的,没有开始点和结束点
- StrokeDashArray、StrokeDashOffset和StrokeDashGap:用于在形状周围创建点划线边框。可控制点划线的尺寸和频率,以及每条点划线开始端和结束端边缘的轮廓
- StrokeLineJoin和StrokeMiterLimit:确定形状拐角处的轮廓。从技术角度看,这些属性影响不同直线相遇的顶点,如矩形的拐角。对于没有拐角的形状,如Line和Ellipse,这些属性不起作用
- Stretch:确定形状如何填充可用的区域。可使用该属性创建能够扩展以适合其容器的形状。还可为 HorizontalAlignment 或 VerticalAlignmet 属性(这些属性继承自FrameworkElement 类)使用 Stretch 值强制形状在某个方向上扩展
- DefiningGeometry:为形状提供 Geometry 对象。Geometry 对象描述了形状的坐标和尺寸,不包括 UIElcment类的相关内容,例如对键盘和鼠标事件的支持。
- GeometryTransform:可通过该属性应用 Transform对象,改变用于绘制形状的坐标系统,从而可扭曲、旋转或移动形状。当为图形应用动画时,变换特别有用。稍后将介绍与变换相关的内容
- RenderedGeometry:提供描述最终的、已渲染好的图形的Geomety对象。第13章将介绍 Geomety 对象
1.1改变形状和尺寸
- 通过硬编码直接设置Height和Width属性。
- 使用StackPanel和Grid等布局控件,然后Fill。
- 使用Canvas容器。顺序越后,越置顶。缺点是固定大小,无法改变自身的尺寸适应不同的窗口大小。
- 使用Viewbox控件。继承自Decorator。通常在Viewbox控件中放置Canvas面板,并在Canvas面板中放置形状。从而实现随着窗口的变化控件形状的变化。
1.2矩形和椭圆
注意:如果未设置Stroke或Fill属性,形状就不会显示。
1.3直线
- 对于直线,Fill属性不起作用,必须设置Stroke属性。
- 在直线中使用的坐标是相对于放置直线的矩形区域左上角的坐标。
- 直线设置 Margin、HorizontalAlignment 以及 VerticalAlignment 属性是没有意义的,因为它们没有任何效果。对于 Polyline 和 Polygon 形状具有同样的限制。
<Line Stroke="Blue" X1="0" Y1="0" X2="10" Y2="100"/>
//更改线起始和结束的形状
<Line Stroke="Blue" X1="0" Y1="0" X2="10" Y2="100" StrokeStartLineCap="Round" StrokeEndLineCap="Triangle"/>
1.4折线
- 可以绘制一系列相互连接的直线。
- 只需要通过points属性提供点的列表,并在每个坐标之间添加空格或逗号。
<Polyline Stroke="Blue" StrokeThickness="5" Points="10,150 30,140 50,160 70,130 90,170 110,120 130,180 150,110 170,190 190,100 210,240"/>
//更改起始和结束形状
<Polyline Stroke="Blue" StrokeThickness="5" StrokeStartLineCap="Round" StrokeEndLineCap="Triangle" Points="10,150 30,140 50,160 70,130 90,170 110,120 130,180 150,110 170,190 190,100 210,240"/>
1.5多边形
- 添加最后一天线段,将最后一个点与开始点连接。
- 可以使用Fill填充内部颜色。
- 下面代码绘制五角星。
<Polygon Stroke="BlueViolet" StrokeThickness="1" Fill="YellowGreen"
FillRule="Nonzero" Points="15,200 68,70 110,200 0,125 135,125"/>
1.6点划线
- 可通过设置StrokeDashArray绘制断开的点划线。
- StrokeDashArray还可以使用费整数值,如StrokeDashArray=“5 0.2 3 0.2”(代表)
- 如果想从中间开始绘制,可使用StrokeDashOffset属性。
// 点划线的实线长度值为1,空白长度值为2,这些都是相对于直线宽度的。
// 直线宽度为14个单位,实线部分的长度就位14个单位,空白部分就是28个单位,依次重复。
<Polyline Stroke="Blue" StrokeThickness="14" StrokeDashArray="1 2"
Points="10,30 60,0 90,40 120,10 350,10"/>
// 这样的设置提供了更复杂序列:5x14单位长的点划线,然后是0.2x15单位长的空白
// 接下来是 3x14单位长的实线和0.2x14单位长的空白。在该序列的尾部,直线从头开始重复该模式。
<Polyline Stroke="Blue" StrokeThickness="14" StrokeDashArray="5 0.2 3 0.2"
Points="10,30 60,0 90,40 120,10 350,10"/>
// 当StrokeDashArray属性提供奇数个数值时。WPF首先绘制3倍直线宽度长的实线,然后是0.5倍直线宽度长的空白,再接下来是2倍直线宽度长的实线。但当再从头开始重复该模式时,首先是3倍直线宽度长的空白,接着是05倍直线宽度长的实线,依此类推。本质上,点划线在线段和空白之间交替其模式。
<Polyline Stroke="Blue" StrokeThickness="14" StrokeDashArray="3 0.5 2"
Points="10,30 60,0 90,40 120,10 350,10"/>
2.画刷
最简单的画刷类型是SolidColorBrush,xaml中设置形状的stroke或fill属性时,使用的是SolidColorBrush,它在后台完成绘制。
- 画刷支持更改通知,因为它们继承自Freezable类。因此,如果改变了画刷,任何使用画
刷的元素都会自动重新绘制自身。 - 画刷支持部分透明。为此,只需要修改 Opacity 属性,使背景能够透过前面的内容进行显
示。本章末尾会尝试这种方法。 - 通过 SystemBrushes 类可以访问这样的画刷:此类画刷使用 Windows 系统设置为当前计
算机定义的首选颜色。
所有画刷都位于System.Windows.Media名称空间中,常见的继承自System.Windows.Media.Brush的类。
- SolidColorBrush:使用单一的连续颜色绘制区域
- LinearGradientBrush:使用渐变填充绘制区域,渐变的阴影填充从一种颜色变化到另一种颜色(并且,也可以在变化到第3种颜色之后再变化到第4种颜色,依此类推)
- RadialGradientBrush:使用径向渐变填充绘制区域,除了是在圆形模式中从中心点向外部辐射渐变之外,这种画刷和线性渐变画刷类似
- ImageBrush:使用可被拉伸、缩放或平铺的图像绘制区域
- DrawingBrush:使用 Drawing 对象绘制区域,该对象可以包含已经定义的形状和位图
- VisualBrush:使用 Visual 对象绘制区域。因为所有 WPF 元素都继承自 Visual 类,所以可使用该画刷将部分用户界面(如按钮的表面)复制到另一个区域。当创建特殊效果时,比如部分反射效果,该画刷特别有用
- BitmapCacheBrush:使用从 Visual 对象缓存的内容绘制区域。这种画刷和 VisualBrush 类似,但如果需要在多个地方重用图形内容或者频繁地重绘图形内容,这种画刷更高效
2.1SolidColorBrush
<Button Height="50">
<Button.Background>
<SolidColorBrush Color="Aquamarine"/>
</Button.Background>
</Button>
2.2LinearGradientBrush
- offset:控制比例,从0-1。
- StartPoint="0 0" EndPoint="1 0"控制方向,引号内的值为X,Y值。(0,0)代表左上角,(1,1)代表右下角,可以理解为比例坐标。
- 可以使用SolidColorBrush的地方都可以使用LinearGradientBrush。
<Button Height="50">
<Button.Background>
<LinearGradientBrush StartPoint="0 0" EndPoint="1 0">
<GradientStop Color="BurlyWood" Offset="0"/>
<GradientStop Color="Red" Offset="0.5"/>
<GradientStop Color="DarkGreen" Offset="1"/>
</LinearGradientBrush>
</Button.Background>
</Button>
2.3RadialGradientBrush
- center,RadiusX和RadiusY联合设置内部渐变圆的边界。默认下center为(0.5,0.5),默认下RadiusX和RadiusY也是0.5。
<Ellipse Margin="5" Stroke="Black" StrokeThickness="1" Width="200" Height="200">
<Ellipse.Fill>
<RadialGradientBrush RadiusX="1" RadiusY="1" GradientOrigin="0.7 0.3" Center="1 1">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="Blue" Offset="1"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
2.4ImageBrush
- 属性Stretch,TileMode,Viewport,ViewPortUnits可更改布局方式
<StackPanel>
<StackPanel.Background>
<ImageBrush ImageSource="/Images/user-circle.png"/>
</StackPanel.Background>
</StackPanel>
3.变换
变换继承自System.Windows.Media.Transform。所有变换都继承自Freezable类,因此支持自动更改通知功能。主要有以下类。
- TranslateTransform:将坐标系统移动一定距离。如果希望在不同的地方绘制相同的形状,该变换非常有用。重要属性X、Y。
- RotateTransform:旋转坐标系统。正常绘制的形状绕着选择的中心点旋转。重要属性Angle、CenterX、CenterY。
- ScaleTransform:放大或缩小坐标系统,从而绘制更大或更小的图形。可在X和Y方向应用不同的缩放度,从而拉伸或压缩形状。重要属性ScaleX、ScaleY、CenterX、CenterY。
- SkewTransform:通过倾斜一定的角度扭曲坐标系统。例如,如果绘制正方形通过该变换正方形会变成平行四边形。重要属性AngleX、AngleY、CenterX、CenterY。
- MatrixTransform:使用提供的矩阵的乘积修改坐标系统。这是最复杂的选择-为实现该变换,需要掌握一些数学技巧。重要属性Matrix。
- TransformGroup:组合多个变换,从而可以一次应用所有这些变换。应用变换的顺序是很重要的,因为这会影响最终结果。例如,首先使用RotateTransform旋转形状,然后使用TranslateTransform移动形状,这样做的结果和先移动再旋转的结果是不同的。
3.1变化形状
- RotateTransform,centerX和centerY是使用的绝对坐标。可通过TransformOrigin属性设置相对坐标。(0,0)为左上角,(1,1)为右下角。
<!--绕原点旋转25度-->
<Rectangle Width="80" Height="10" Stroke="blue" Fill="Yellow" InkCanvas.Left="100" InkCanvas.Top="100">
<Rectangle.RenderTransform>
<RotateTransform Angle="25"/>
</Rectangle.RenderTransform>
</Rectangle>
<!--绕45,5点旋转45度-->
<Rectangle Width="80" Height="10" Stroke="blue" Fill="Yellow" InkCanvas.Left="100" InkCanvas.Top="100">
<Rectangle.RenderTransform>
<RotateTransform Angle="45" CenterX="45" CenterY="5"/>
</Rectangle.RenderTransform>
</Rectangle>
<!--绕中心点旋转45度-->
<Rectangle Width="80" Height="10" Stroke="blue" Fill="Yellow"
InkCanvas.Left="100" InkCanvas.Top="100" RenderTransformOrigin="0.5 0.5">
<Rectangle.RenderTransform>
<RotateTransform Angle="45"/>
</Rectangle.RenderTransform>
</Rectangle>
3.2变换元素
RenderTransform 和 RenderTransformOrigin 属性并不限制只能用于形状。实际上,Shape 类的这些属性从 UIElement类继承而来,这意味着所有 WPF 元素都支持这两个属性,包括按钮、文本框、TextBlock 控件、充满内容的整个布局容器等。令人感到惊讶的是,可旋转、扭曲以及缩放 WPF 用户界面中的任意一部分(尽管在大多数情况下不会这么做)。
只有很少几个元素不能被变换,因为它们的呈现工作并非由 WPF 本身负责。不能被变换的
元素的两个例子是 WindowsFormHost和 WebBrower 元素,WindowsFormHost 元素用于在 WPF
窗口中放置 Windows 窗体控件,WebBrower 元素用于显示 HTML 内容。
4.透明
4.1元素透明
- 设置元素的 Opacity 属性。每个元素(包括形状)都从 UIElement基类继承了 Opacity 属性。不透明度(Opacity)是0到1之间的小数,1表示完全不透明(默认值),0表示完全透明。例如,不透明度 0.9 会创建 90%可见(10%透明)的效果。当使用这种方法设置不透明度时,设置会被应用于整个元素的可见内容。
- 设置画刷的 Opacity属性。每个画刷也从 Bnush 基类继承了 Opacity 属性。可使用0到1之间的值设置该属性,以控制使用画刷绘制的内容的透明度--不管是固定颜色画刷、渐变画刷,还是某种类型的纹理或图像画刷。因为可为形状的 Stroke 和 Fi 属性使用不同的画刷,所以可为边框和表面区域设置不同程度的透明度。
- 使用具有透明 Alpha 值的颜色。所有 alpha 值小于 255 的颜色都是半透明的。例如,可在SolidColorBrush 画刷中使用半透明颜色,并使用该画刷绘制元素的前景内容和背景表面在有些情况下,使用半透明颜色比设置 Opacity 属性执行得更好。
4.2透明掩码
Opacity 属性使元素的所有内容都是部分透明的。OpacityMask属性提供了更大的灵活性。可使元素的特定区域透明或部分透明,从而实现各种常见的以及新颖的效果。例如,可使用OpacityMask属性将形状逐渐褪色到完全透明。