在Android 我们需要在屏幕画图,或扩展SurfaceView 或扩展父类View 在OnDraw()里面使用画板和调色笔画画。而在微软的强大封装下,这种画图的试成为了控件的可能,微软将众多日常必要的画图都以控件展示,开发人员则无须过多学习使用Paint 、使用Canvas 等画图知识就能轻松在WP7 手机上画各种图,不过这种灵活性是否会降低呢?这个姑且不深究。

  今天学习的WP7 画图控件有以下几种:

  • InkPresenter 可否单纯理解为画图面板?
  • Path 路径
  • Ellipse 圆形或椭圆形
  • Rectangle 矩形,方块矩形或圆角矩形
  • Line 直线
  • Polygon 封闭多边形
  • Polyline 开放多边形

1.InkPresenter 实现方式:

为其添加三个事件监听,实现其按下到离开的画图路径:

 

            <InkPresenter Background="White" LostMouseCapture="inkPresenter1_LostMouseCapture"  MouseLeftButtonDown="inkPresenter1_MouseLeftButtonDown" MouseMove="inkPresenter1_MouseMove" Height="471" HorizontalAlignment="Left" Margin="24,25,0,0" Name="inkPresenter1" VerticalAlignment="Top" Width="411" />

 

 

监听内部实现代码都有添加注释,代码如下:

 

 public partial class InkPresenterPage : PhoneApplicationPage
    {
        
//从手指落下到抬起就称为一个Stroke
        Stroke mStroke;

        
public InkPresenterPage()
        {
            InitializeComponent();
        }

        
private void inkPresenter1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            
//捕捉按下动作
            inkPresenter1.CaptureMouse();
            
//一个按下触发的动作为stroke ,对于这些stroke 的点为stylusPoint,故要创建一个集合的点
            StylusPointCollection spc = new StylusPointCollection();
            
//从inkPresenter 中得到每个stylusPoint 并添加到集合里面
            spc.Add(e.StylusDevice.GetStylusPoints(inkPresenter1));
            
//实例化一个stroke到inkPresenter里面
            mStroke = new Stroke();
            
//将stroke 添加
            this.inkPresenter1.Strokes.Add(mStroke);
        }

        
/// <summary>
        
/// 当手指移动时,将styluspoint 存进stroke 
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>
        private void inkPresenter1_MouseMove(object sender, MouseEventArgs e)
        {
            
if (mStroke!=null)
            {
                mStroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(inkPresenter1));
            }
           
        }

        
/// <summary>
        
/// 当弹起时重新初始化stroke 为null
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>
        private void inkPresenter1_LostMouseCapture(object sender, MouseEventArgs e)
        {
            mStroke 
= null;
        }

        
/// <summary>
        
/// 清空inkPresenter里面的Stroke
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            
this.inkPresenter1.Strokes.Clear();
        }

 

  最终实现效果:

 

2.Path 路径

  Path 是众多画图控件使用起来较为麻烦的一个。因为其可以通过两种绘制的方式绘制图形,分别为如下:

  • Markup Syntax 可以绘制一个系列的线条
  • Geometries 绘制形状,

以一个圆形的Path 图形为例,通过实现EllipseGeometries 绘制图形,实现代码如下:

 

 <Path   Height="428"
                  HorizontalAlignment
="Left"
                  Margin
="30,80,0,0" 
                  Name
="path1" 
                  Stroke
="Red" 
                  StrokeThickness
="10" VerticalAlignment="Top" Width="456" Fill="Blue">
                
<Path.Data>
                    
<EllipseGeometry Center="200,200" RadiusX="30" RadiusY="30"/>
                
</Path.Data>
            
</Path>

 

另外Path 还支持Path.Data 数据集,即使用GeometryGroup,在对应的下文可以添加多个形状的图形,代码如下:

 

  <Path Height="558" HorizontalAlignment="Left" Margin="10,210,0,0" Name="path2" Stroke="Red" StrokeThickness="10" Fill="White" VerticalAlignment="Top" Width="450" >
                
<Path.Data>
                    
<GeometryGroup FillRule="EvenOdd" >
                        
<EllipseGeometry Center="200,350" RadiusX="30" RadiusY="30"/>
                        
<RectangleGeometry Rect="150,350,200,100"/>
                    
</GeometryGroup>
                
</Path.Data>
            
</Path>

 

Tip:GeometryGroup 的FillRule 分为两种模式,一种为“不叠加-Evenodd”,另一种为“叠加-Nonzero”。

 

Path 的另外一种实现方式为系列线实现模式,实现此模式须把Fill  去掉,否则会在线条之间填充颜色值。实现此系列线相对要复杂一些,必须掌握一定的mini Language 为其添加Data,下面是一些Mini Language 的命令:

  •  移动命令:
                M:绝对起始点 m:相对于前一点的起始点 如:M 100 ,200 M即Move 移动,移动到Left:100,Top:200这个位置开始
  • 直线命令:
                L:L/l 直线的结束点,如:L 100,200 即画从M的开始点左画100并停留在Top为200的位置,在这个位置开始弯折
  • 水平线命令:
                H:水平线的长度
  • 垂线命令:
                V:垂直线的长度
  •  二次贝赛尔曲线命令:
                Q:控制点坐标,结束点坐标
                如:Q 100 ,200 300,200
  •  三次贝赛尔曲线命令:
                C:控制点坐标,控制点坐标,结束点坐标
  •  光滑二次贝赛尔曲线命令:
                T:控制点坐标,结束点坐标
                如:T 100,200 300,200
  •  光滑三次贝赛 尔曲线命令:
                S:控制点坐标,结束点坐标
                如:S 100,200 200,300
  • 圆弧命令:
                A:弧大小(半径值)、弧角、优弧弧标记(1大于等于180度,0小于180度)、正负弧标记、结束点
                如:A 5,5 0 0 0 10,10
  •  闭合命令:
                Z:将创建的曲线封闭

下面给出一个实现的样例代码:

 

 <Path   Height="428"
                  HorizontalAlignment
="Left"
                  Margin
="12,207,0,0" 
                  Name
="path3" 
                  Stroke
="Red" 
                    Data
="M 10,40 L 300,40 V100 H 240 C 100,200 200,400 300,200 S 300,240 400,175 "
                  StrokeThickness
="10" VerticalAlignment="Top" Width="456"  /> 

 

 

上面三个实现的Path 效果分别为下图:

 

3.Ellipse 圆形或椭圆形

  Ellipse 使用起来就比较简单,只要注意设置它的高和宽之间的大小,实现代码如下:

 

 <Ellipse Height="100" HorizontalAlignment="Left" Margin="111,32,0,0" Name="ellipse1" Stroke="Red" StrokeThickness="1" VerticalAlignment="Top" Width="200" />
            
<Ellipse Height="100" HorizontalAlignment="Left" Margin="161,223,0,0" Name="ellipse2" Stroke="Red" StrokeThickness="1" VerticalAlignment="Top" Width="100" />

 

 

实现效果:

 

4.Rectangle 矩形,方块矩形或圆角矩形

  跟上面的Ellipse 实现也同样方便,注意设置它的RadiusX 和 RadiusY ,代码如下:

 

 <Rectangle Height="100" HorizontalAlignment="Left" Margin="133,48,0,0" Name="rectangle1" Stroke="Red" StrokeThickness="1" VerticalAlignment="Top" Width="200" />
            
<Rectangle Height="100" RadiusX="50" RadiusY="50" HorizontalAlignment="Left" Margin="133,274,0,0" Name="rectangle2" Stroke="Red" StrokeThickness="1" VerticalAlignment="Top" Width="200" />

 

 

实现效果如下图:

 

5.Line 直线

直线需要注意的是它有四个坐标要设置,即X1 Y1 X2 Y2,x代表直线起始点和结束点的相对自己的位置,相同则成垂直,如果不相等则倾斜或者横放,Y 代表两点之间的长度,以Y1为起点画到Y2为结束点,实例代码如下:

 

  <Line Height="10" X1="10" Y1="10" X2="350" Y2="10"    HorizontalAlignment="Left" Margin="52,63,0,0" Name="line1" Stroke="Red" StrokeThickness="5" VerticalAlignment="Top" Width="360" />
            
<Line Height="314" HorizontalAlignment="Left" Margin="56,124,0,0" Name="line2" Stroke="Yellow" StrokeThickness="5" VerticalAlignment="Top" Width="360" X1="200" X2="200" Y1="10" Y2="300" />

 

 

上图代码,实现效果如下:

 

6.Polygon 封闭多边形

封闭多边形:两两数字分为一边,以x,y的形式画边.可以任意组合多组坐标,示例代码如下:

 

  <Polygon Height="314" HorizontalAlignment="Left" Fill="Yellow" Points="200,10 10,300 400,300" Margin="14,27,0,0" Name="polygon1" Stroke="Red" StrokeThickness="5" VerticalAlignment="Top" Width="411" />

 

 

上面代码实现效果如下:

 

7.Polyline 开放多边形

非封闭多边形:以封闭多边形的三角从标为例,上图为封闭多边形的三角形写法,可以看出图上并不为我们封闭。要做封闭必须自己手动再添加封闭线,示例代码如下:

 

 <Polyline Height="186" HorizontalAlignment="Left" Margin="9,22,0,0" Points="150,10 10,150 300,150" Name="polyline1" Stroke="Red" StrokeThickness="5" VerticalAlignment="Top" Width="438" />
            
<Polyline Height="186" HorizontalAlignment="Left" Margin="12,214,0,0" Name="polyline2" Points="150,10 10,150 300,150 150,10" Stroke="Red" StrokeThickness="5" VerticalAlignment="Top" Width="438" />

 

 

上面代码实现效果如下:

 

可以看出,相对于Android 的画图要来得轻松方便许多,如果可以开放这些接口在自定义控件的时候可以为控件画图效果那就更好了,类似于Android 的OnDraw面板。

 

×××:点击这里

本篇代码和实现原理参考自 小镇 Windows Phone 7画图视频。