WPF:使用鼠标在Canvas面板上画线

来源:互联网 发布:淘宝卖id篮球鞋的店铺 编辑:程序博客网 时间:2024/05/17 09:25

   使用Canvas+Line 任意画线


         主要使用布局面板Canvas作为背景,通过其属性Children添加Line 来实现画线。可以理解为 每一个Line 就是一个点。
         不清楚Canvas的用法可以参见:点击打开链接  Line的参见:点击打开链接


   操作效果


       
   
       按下鼠标左键任意画线,可以修改线的颜色(红色,绿色)修改线的样式(实线,虚线)。后期增加导出生成图片功能。

   代码解析

         线由点组成,当然我这里的点其实就是线。线由开始点与结束点构成,想必看到过msdn上line的解释就会一目了然。至于鼠标事件,会有鼠标左键按下以及移动,松开动作。 还需要有个一集合来存放点,取名为List<Point> 类型。  在鼠标按下事件中可以这样写:
        
/// <summary>        /// 起始位置        /// </summary>        Point startPoint;        /// <summary>        /// 点集合        /// </summary>        List<Point> pointList = new List<Point>();        /// <summary>        /// 鼠标左键按下获取开始Point        /// </summary>        private void Canvas_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)        {            startPoint = e.GetPosition(myCanvas);        }
         记录开始位置startPoint 。按下之后随之的就是Move动作,在移动事件中这样写:
 
 
/// <summary>        /// 按下鼠标左键移动        /// </summary>        private void Canvas_PreviewMouseMove(object sender, MouseEventArgs e)        {            if (e.LeftButton == MouseButtonState.Pressed)            {                // 返回指针相对于Canvas的位置                Point point = e.GetPosition(myCanvas);                if (pointList.Count == 0)                {                    // 加入起始点                    pointList.Add(new Point(this.startPoint.X, this.startPoint.Y));                }                else                {                    // 加入移动过程中的point                    pointList.Add(point);                }                // 去重复点                var disList = pointList.Distinct().ToList();                var count = disList.Count(); // 总点数                if (point != this.startPoint && this.startPoint != null)                {                    var l = new Line();                    string color = (cboColor.SelectedItem as ComboBoxItem).Content as string;                    if (color == "默认")                    {                        l.Stroke = Brushes.Black;                    }                    if (color == "红色")                    {                        l.Stroke = Brushes.Red;                    }                    if (color == "绿色")                    {                        l.Stroke = Brushes.Green;                    }                    l.StrokeThickness = 1;                    if (count < 2)                        return;                    l.X1 = disList[count - 2].X;  // count-2  保证 line的起始点为点集合中的倒数第二个点。                    l.Y1 = disList[count - 2].Y;                    // 终点X,Y 为当前point的X,Y                    l.X2 = point.X;                    l.Y2 = point.Y;                    myCanvas.Children.Add(l);                }            }        }

       移动过程中创建Line对象并加入Canvas中。    代码中的颜色判断最好修改成枚举类型。

    修改线颜色及样式

          这部分比较简单,直接遍历Canvas中的Line对象,修改Line的Stroke属性,StrokeDashArray属性。

/// <summary>        /// 选择颜色        /// </summary>        private void cboColor_SelectionChanged(object sender, SelectionChangedEventArgs e)        {            string color = (cboColor.SelectedItem as ComboBoxItem).Content as string;            if (this.myCanvas != null)            {                List<Line> list = GetChildObjects<Line>(this.myCanvas);                if (list.Count > 0)                {                    list.ForEach(l =>                    {                        if (color == "默认")                        {                            l.Stroke = Brushes.Black;                        }                        if (color == "红色")                        {                            l.Stroke = Brushes.Red;                        }                        if (color == "绿色")                        {                            l.Stroke = Brushes.Green;                        }                    });                    list.Clear();                }            }        }


/// <summary>        /// 选择style        /// </summary>        private void cboStyle_SelectionChanged(object sender, SelectionChangedEventArgs e)        {            string style = (cboStyle.SelectedItem as ComboBoxItem).Content as string;            if (this.myCanvas == null)            {                return;            }            List<Line> list = GetChildObjects<Line>(this.myCanvas);            if (list.Count > 0)            {                list.ForEach(l =>                {                    if (style == "默认")                    {                        l.StrokeDashArray = new DoubleCollection(new List<double>() { });                    }                    if (style == "虚线")                    {                        l.StrokeDashArray = new DoubleCollection(new List<double>() {                      1,1,1,1                    });                    }                });                list.Clear();            }        }

GetChildObjects 方法参见博客文章。
          

   前台XAML

              主要用到了WrapPanel,StackPanel布局控件。

<WrapPanel>        <StackPanel>            <WrapPanel>                <Label Content="颜色:" VerticalAlignment="Center"></Label>                <ComboBox x:Name="cboColor" SelectedIndex="0" Width="120" Margin="10" SelectionChanged="cboColor_SelectionChanged">                    <ComboBoxItem>默认</ComboBoxItem>                    <ComboBoxItem>红色</ComboBoxItem>                    <ComboBoxItem>绿色</ComboBoxItem>                </ComboBox>            </WrapPanel>            <WrapPanel>                <Label Content="样式:" VerticalAlignment="Center"></Label>                <ComboBox x:Name="cboStyle" Width="120" Margin="10" SelectionChanged="cboStyle_SelectionChanged">                    <ComboBoxItem IsSelected="True">默认</ComboBoxItem>                    <ComboBoxItem>虚线</ComboBoxItem>                </ComboBox>            </WrapPanel>        </StackPanel>        <Canvas Width="500" Height="500" Background="Gray" x:Name="myCanvas" PreviewMouseLeftButtonDown="Canvas_PreviewMouseLeftButtonDown" PreviewMouseMove="Canvas_PreviewMouseMove">        </Canvas>    </WrapPanel>



       

0 1