WPF绘图

  1. 云栖社区>
  2. 博客>
  3. 正文

WPF绘图

nurmemet 2019-04-14 16:03:32 浏览353
展开阅读全文

添加一个绘图面板
项目按右键添加类DrawingPanel

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Drawing

{
    class DrawingPanel :Panel

    {
        //所有图形
        private  List<Visual> visuals = new List<Visual>();
        private List<DrawingVisual> hits=new List<DrawingVisual>();


        protected override Visual GetVisualChild(int index)
        {
            return   visuals[index];
        }

        protected override int VisualChildrenCount
        {
            get
            {
                return visuals.Count;
            }
        }


        public void addVisuals(Visual visual)
        {
            visuals.Add(visual);
            base.AddVisualChild(visual);
            base.AddLogicalChild(visual);
        }

        public void DeleteVisual(Visual visual)
        {
            visuals.Remove(visual);
            base.RemoveVisualChild(visual);
            base.RemoveLogicalChild(visual);
        }

        public DrawingVisual GetVisual(Point point)
        {

            HitTestResult hitTestResult = VisualTreeHelper.HitTest(this,point);
            return hitTestResult.VisualHit as DrawingVisual;
        }

        //
        public List<DrawingVisual> GetVisuals(Geometry geometry)
        {
            hits.Clear();
            GeometryHitTestParameters parameters = new GeometryHitTestParameters(geometry);
            HitTestResultCallback callback = new HitTestResultCallback(this.HitTestResultCallback);
            VisualTreeHelper.HitTest(this, null, callback, parameters);
            return hits;
        }

        //HitTest回调函数
        private HitTestResultBehavior HitTestResultCallback(HitTestResult result)
        {
            GeometryHitTestResult geometryHitTest = (GeometryHitTestResult)result;
            DrawingVisual visual = geometryHitTest.VisualHit as DrawingVisual;
            if (visual != null && geometryHitTest.IntersectionDetail == IntersectionDetail.FullyInside)
            {
                hits.Add(visual);
            }
            return HitTestResultBehavior.Continue;
        }
    }
}

然后是在窗口中使用
以下是布局VisualLayer.xmal代码(项目按右键-WPF项目-窗口)

<Window x:Class="WpfApp1.VisualLayer"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        xmlns:local1="clr-namespace:Drawing"
        mc:Ignorable="d"
        Title="VisualLayer" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions >
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <ToolBarTray Orientation="Vertical">
            <ToolBar>
                <RadioButton Margin="0,3" Name="cmdSelectMove">
                    <StackPanel>
                        <Image Source="pointer.png" Width="35" Height="35"></Image>
                        <TextBlock>Select/Move</TextBlock>
                    </StackPanel>
                </RadioButton>
                <RadioButton Margin="0,3" IsChecked="True" Name="cmdAdd">
                    <StackPanel>
                        <Rectangle Width="30" Height="30" Stroke="SteelBlue" StrokeThickness="3" Fill="AliceBlue">
                        </Rectangle>
                        <TextBlock>Add Square</TextBlock>
                    </StackPanel>
                </RadioButton>
                <RadioButton Margin="0,3" Name="cmdDelete">
                    <StackPanel>
                        <Path Stroke="SteelBlue" StrokeThickness="4" StrokeEndLineCap="Round" Fill="Red" HorizontalAlignment="Center">
                            <Path.Data>
                                <GeometryGroup>
                                    <PathGeometry>
                                        <PathFigure StartPoint="0,0">
                                            <LineSegment Point="18,18"></LineSegment>
                                        </PathFigure>
                                        <PathFigure StartPoint="0,18">
                                            <LineSegment Point="18,0"></LineSegment>
                                        </PathFigure>
                                    </PathGeometry>
                                </GeometryGroup>
                            </Path.Data>
                        </Path>
                        <TextBlock> Delete Square</TextBlock>
                    </StackPanel>
                </RadioButton>
                <RadioButton Margin="0,3" Name="cmdSelecMultipe" >
                    <StackPanel>
                        <Image Source="pointer.png" Width="35" Height="35"></Image>
                        <TextBlock>Select Multiple</TextBlock>
                    </StackPanel>
                </RadioButton>
            </ToolBar>
        </ToolBarTray>
        <Border Grid.Column="1" Margin="3" BorderBrush="SteelBlue" BorderThickness="1">
            <local1:DrawingPanel x:Name="drawingSurface" Background="White" ClipToBounds="True" MouseLeftButtonDown="drawingSurface_MouseLeftButtonDown"
                MouseLeftButtonUp="drawingSurface_MouseLeftButtonUp"
                MouseMove="drawingSurface_MouseMove">
            </local1:DrawingPanel>
        </Border>
    </Grid>
</Window>

VisualLayer.xaml.cs代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace WpfApp1
{
    /// <summary>
    /// VisualLayer.xaml 的交互逻辑
    /// </summary>
    public partial class VisualLayer : Window
    {

        private Brush drawingBrush = Brushes.AliceBlue;
        private Brush selectedDrawingBrush = Brushes.LightGoldenrodYellow;
        private Pen drawingPen = new Pen(Brushes.SteelBlue, 3);
        private Size squareSize = new Size(30, 30);
        private DrawingVisual drawingVisual;
        private Vector clickOffset;
        private bool isDragging;
        private DrawingVisual selectedVisual;
        private bool isMultiSelecting = false;
        private Point selectionSquareTopLeft;
        private Brush selectionSquareBrush = Brushes.Transparent;
        private Pen selectionSquarePen = new Pen(Brushes.Black, 2);
        private DrawingVisual selectionSquare;
        

        public VisualLayer()
        {
            InitializeComponent();
            DrawingVisual v = new DrawingVisual();
            DrawingSquare(v, new Point(10,10), false);
        }


        private void DrawingSquare(DrawingVisual v,Point topLeftCorner,bool isSelected)
        {
            using(DrawingContext dc = v.RenderOpen())
            {
                Brush brush = drawingBrush;
                if (isSelected) brush = selectedDrawingBrush;

                dc.DrawRectangle(brush, drawingPen, new Rect(topLeftCorner, squareSize));

            }
        }


        private void drawingSurface_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Point pointClicked = e.GetPosition(drawingSurface);
            if (cmdAdd.IsChecked==true)
            {
                DrawingVisual drawingVisual = new DrawingVisual();
                DrawingSquare(drawingVisual, pointClicked, false);
                drawingSurface.addVisuals(drawingVisual);
            }
            else if (cmdDelete.IsChecked == true)
            {
                DrawingVisual drawingVisual = drawingSurface.GetVisual(pointClicked);
                if (drawingVisual != null) drawingSurface.DeleteVisual(drawingVisual);
            }
            else if (cmdSelectMove.IsChecked == true)
            {
                DrawingVisual visual = drawingSurface.GetVisual(pointClicked);
                if (visual != null)
                {
                    Point topLeftCorner = new Point(
                        visual.ContentBounds.TopLeft.X + drawingPen.Thickness / 2,
                        visual.ContentBounds.TopLeft.Y + drawingPen.Thickness / 2);
                    DrawingSquare(visual, topLeftCorner, true);

                    clickOffset = topLeftCorner - pointClicked;
                    isDragging = true;

                    if (selectedVisual != null && selectedVisual != visual)
                    {
                        // The selection has changed. Clear the previous selection.
                        ClearSelection();
                    }
                    selectedVisual = visual;
                }

            } else if (cmdSelecMultipe.IsChecked == true)
            {
                selectionSquare = new DrawingVisual();

                drawingSurface.addVisuals(selectionSquare);

                selectionSquareTopLeft = pointClicked;
                isMultiSelecting = true;

                // Make sure we get the MouseLeftButtonUp event even if the user
                // moves off the Canvas. Otherwise, two selection squares could be drawn at once.
                drawingSurface.CaptureMouse();
            }
        }

        private void ClearSelection()
        {
            Point topLeftCorner = new Point(
                        selectedVisual.ContentBounds.TopLeft.X + drawingPen.Thickness / 2,
                        selectedVisual.ContentBounds.TopLeft.Y + drawingPen.Thickness / 2);
            DrawingSquare(selectedVisual, topLeftCorner, false);
            selectedVisual = null;
        }

        private void drawingSurface_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDragging)
            {
                Point pointDragged=e.GetPosition(drawingSurface)+clickOffset;
                DrawingSquare(selectedVisual, pointDragged, true);

            }
            else if(isMultiSelecting)
            {
                Point pointDragged = e.GetPosition(drawingSurface);
                DrawSelectionSquare(selectionSquareTopLeft, pointDragged);
            }
        }

        private void DrawSelectionSquare(Point point1, Point point2)
        {
            selectionSquarePen.DashStyle = DashStyles.Dash;
            using(DrawingContext dc= selectionSquare.RenderOpen())
            {
                dc.DrawRectangle(selectionSquareBrush, selectionSquarePen,
                    new Rect(point1, point2));
            }
        }

        private void drawingSurface_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            isDragging = false;
            if (isMultiSelecting)
            {
                RectangleGeometry geometry = new RectangleGeometry(
                    new Rect(selectionSquareTopLeft, e.GetPosition(drawingSurface)));
                List<DrawingVisual> visualsInRegion =
                    drawingSurface.GetVisuals(geometry);
                MessageBox.Show(String.Format("You selected {0} square(s).", visualsInRegion.Count));

                isMultiSelecting = false;
                drawingSurface.DeleteVisual(selectionSquare);
                drawingSurface.ReleaseMouseCapture();
            }
        }
    }
}

效果图
image

网友评论

登录后评论
0/500
评论
nurmemet
+ 关注