wpf drag the mouse to draw geometry

Recently, in learning wpf, I simply used the Button control to create a drawing of free lines, lines, rectangles and circles. There are not many learning events, so I just use the control to complete these functions, Class is not used for editing (if class is used, more functions can be realized. For example, select the drawn drawing to edit the drawing parameters to change the size of the drawing. Then use class to complete the drawing command and rewrite it).

To realize these functions, wpf should be built first xaml interface.

 <Grid Margin="3" x:Name="grid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"></ColumnDefinition>
            <ColumnDefinition Width="3*"></ColumnDefinition>            
        </Grid.ColumnDefinitions>
        <Grid x:Name="grid1" Grid.Column="0">
            <Grid.RowDefinitions>
                <RowDefinition Height="*"></RowDefinition>
                <RowDefinition Height="*"></RowDefinition>
                <RowDefinition Height="*"></RowDefinition>
                <RowDefinition Height="*"></RowDefinition>
                <RowDefinition Height="*"></RowDefinition>
            </Grid.RowDefinitions>
            <Button Height="30" Margin="5" Grid.Row="0" Name="PathLine" Click="button0">Draw lines at will</Button>
            <Button Height="30" Margin="5" Grid.Row="1" Name="Line" Click="button1">Draw a straight line</Button>
            <Button Height="30" Margin="5" Grid.Row="2" Name="Rect" Click="button2">Draw rectangle</Button>
            <Button Height="30" Margin="5" Grid.Row="3" Name="Elli" Click="button3">Draw a circle</Button>
            <Button Height="30" Margin="5" Grid.Row="4" Click="Button_Clear" Content="empty"/>
        </Grid>
        <Canvas Grid.Column="1" Margin="3" x:Name="canvas1" Background="Gray" MouseLeftButtonDown="Canvas_MouseButtonDown" 
                MouseLeftButtonUp="Canvas_MouseButtonUp" MouseMove="Canvas_MouseMove"/>        
    </Grid>

The edited meeting should be as shown in the following figure:

After that, the response event of the control is generated. The generation of the Button event will not be repeated, but directly to the code:

        private void button1(object sender, RoutedEventArgs e)
        {
            this.Type = TypeEnum.Draw a straight line;
        }

        private void button2(object sender, RoutedEventArgs e)
        {
            this.Type = TypeEnum.rectangle;
        }

        private void button3(object sender, RoutedEventArgs e)
        {
            this.Type = TypeEnum.circular;
        }       

        private void button0(object sender, RoutedEventArgs e)
        {
            this.Type = TypeEnum.arbitrarily;
        }

        private void Button_Clear(object sender, RoutedEventArgs e)
        {
            canvas1.Children.Clear();
        }

Here, the enumeration method is used in the Button event,

public enum TypeEnum { Null = 0, Draw a straight line, arbitrarily, rectangle, circular }

This is to respond to the graphics to be drawn corresponding to the events of the mouse button.

For mouse events, I use MouseLeftButtonDown, MouseLeftButtonDown and MouseMove,

I tried to use mousebutton down (Up) directly, but it seems that the right mouse button is used by default. I'd better write it in detail in the code.

Before generating the response command to the Mouse event, several variables are defined:

        private Path path = null;//initialization
        bool isMouseDowm = false;
        private TypeEnum Type = TypeEnum.Null;
        public Point startPoint;

The response code corresponding to the Mouse event is as follows:

        private void Canvas_MouseButtonDown(object sender, MouseButtonEventArgs e)
        {
            startPoint = e.GetPosition(canvas1);
            isMouseDowm = true;
        }

        private void Canvas_MouseButtonUp(object sender, MouseButtonEventArgs e)
        {            
            isMouseDowm = false;
            this.path = new Path();
        }
                
        private void Canvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (isMouseDowm)
            {
                if (Type == TypeEnum.arbitrarily)
                {
                    this.path = new Path();//instantiation 
                    this.path.Stroke = Brushes.Black;
                    this.path.StrokeThickness = 3;

                    PathGeometry pg = new PathGeometry();//Complex graphics
                    PathFigure pf = new PathFigure();//Part of complex graphics
                    pf.StartPoint = startPoint;

                    LineSegment ls = new LineSegment();//Use line to connect two points
                    ls.Point = e.GetPosition(canvas1);

                    pf.Segments.Add(ls);
                    pg.Figures.Add(pf);
                    //Reassign startPoint
                    startPoint = e.GetPosition(canvas1);//The position the mouse moves to is the new starting point

                    this.path.Data = pg;
                    canvas1.Children.Add(this.path);                    
                }
                else if (Type == TypeEnum.Draw a straight line)
                {
                    //Method 1
                    //canvas1.Children.Remove(this.path);
                    //this.path = new Path();
                    //this.canvas1.Children.Add(this.path);
                    //this.path.Stroke = Brushes.Black;
                    //this.path.StrokeThickness = 3;
                    //LineGeometry lg = new LineGeometry(startPoint, e.GetPosition(canvas1));
                    //this.path.Data = lg;

                    //Method 2          
                    //There are two kinds of judgments: one is to click to draw a straight line first, and the other is to click other buttons
                    if (this.path == null)
                    {
                        this.path = new Path();//Judge whether the conditions are met
                        canvas1.Children.Add(this.path);
                    }
                    this.path.Stroke = Brushes.Green;
                    this.path.StrokeThickness = 3;
                    this.path.Data = new LineGeometry(startPoint, e.GetPosition(canvas1));
                    if (this.path != null)
                    {
                        canvas1.Children.Remove(this.path);
                        this.path.Data = new LineGeometry(startPoint, e.GetPosition(canvas1));
                        canvas1.Children.Add(this.path);
                    }
                }
                else if (Type == TypeEnum.rectangle)
                {
                    canvas1.Children.Remove(this.path);
                    this.path = new Path();
                                      
                    this.path.Stroke = Brushes.Red;
                    this.path.StrokeThickness = 3;
                    
                    RectangleGeometry rg = new RectangleGeometry();
                    double startX = startPoint.X;
                    double startY = startPoint.Y;
                    double height = Math.Abs(e.GetPosition(canvas1).X - startPoint.X);
                    double width = Math.Abs(e.GetPosition(canvas1).Y - startPoint.Y);
                    rg.Rect = new Rect(startX, startY, width, height);
                    this.path.Data = rg;
                    canvas1.Children.Add(this.path);                   
                }
                else if (Type == TypeEnum.circular)
                {
                    canvas1.Children.Remove(this.path);
                    this.path = new Path();
                    
                    this.path.Stroke = Brushes.Blue;
                    this.path.StrokeThickness = 3;
                    double startX = startPoint.X;
                    double startY = startPoint.Y;
                    double radiusX = Math.Abs(e.GetPosition(canvas1).X - startPoint.X);
                    double radiusY = Math.Abs(e.GetPosition(canvas1).Y - startPoint.Y);
                    EllipseGeometry eg = new EllipseGeometry(new Point(startX, startY), radiusX, radiusY);
                    this.path.Data = eg;
                    canvas1.Children.Add(this.path);
                }                
            }
        }

The part that draws a straight line, The Remove command was used to eliminate the previous path line (because I use LineGeometry, if I don't erase the previous path, a fan-shaped graph composed of countless lines will be drawn instead of dynamically realizing the emergence of a straight line). Then, in the process of rectangular drawing, the calculation commands of light and height should be light = x2-x1, height = y2-y1, but the drawing cannot respond to mousebuttonup, resulting in that the drawing cannot end The situation, that big guy knows, I hope he can give me some guidance.

Notes are not written too much. It mainly uses several derived classes of Geometry: PathGeometry, LineGeometry, rectangle Geometry and EllipseGeometry. The drawing method is to determine the starting point and end point, and calculate the response according to different drawing requirements (length, width and radius of circle (ellipse, RadiusX and RadiusY)).

In general, the object-oriented thinking is not reflected (because there is no encapsulation, polymorphism and inheritance of classes and methods in classes). If you want to rewrite this article with object-oriented thinking, I still hope you guys can give us some advice. Thank you.

Keywords: C# WPF

Added by jaikob on Tue, 04 Jan 2022 11:08:39 +0200