C# WPF上位机开发(增强版绘图软件)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        前面我们写过一个绘图软件,不过那个比较简单,主要就是用鼠标模拟pen进行绘图。实际应用中,另外一种使用比较多的场景,就是绘制直线、长方形和圆形。不管是流程图,还是传感器仿真,或者是图形数据动态显示等等,绘图部分本身还是有着重要的实际用途。因此,这里有必要告诉大家,实际的canvas绘图是什么样的。

        这里的增强版,主要也是指的直线绘图、长方形绘图和圆形绘图。当然如果要做得好的话,一般还需要同步考虑一下keyboard事件,这部分也很重要。

1、软件设计

        关于软件设计,目前是这么考虑的。可以创建一个菜单,里面有三个子菜单,这三个子菜单分别是直线、长方形和圆形。我们选择了一种图形,那么其他的图形就自动被放弃。后续在canvas上面绘图的时候,就用对应子菜单的形式进行绘图即可。

2、界面设计

        相对代码,界面设计还是比较简单的。整个界面主要就两个部分,一部分是菜单,一部分是canvas。做好了这个,基本的界面就准备好了。

<Window x:Class="WpfApp.MainWindow"
        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:WpfApp"
        mc:Ignorable="d"
        Title="Canvas" Height="450" Width="600">
    <Grid>
        <Menu Name="shapesMenu">
            <MenuItem Header="Shapes">
                <MenuItem Name="menuItemLine" Header="Line" IsCheckable="True" IsChecked="false" Checked="MenuItemLine_Checked"/>
                <MenuItem Name="menuItemRectangle" Header="Rectangle" IsCheckable="True" IsChecked="False" Checked="MenuItemRectangle_Checked"/>
                <MenuItem Name="menuItemCircle" Header="Circle" IsCheckable="True" IsChecked="False" Checked="MenuItemCircle_Checked"/>
            </MenuItem>
        </Menu>
        <Canvas Name="drawingCanvas" Background="WhiteSmoke" MouseDown="Canvas_MouseDown" MouseMove="Canvas_MouseMove" MouseUp="Canvas_MouseUp" Margin="0,20,0,10"/>
    </Grid>
</Window>

3、代码设计

        由于是绘图,所以整个绘图的操作其实分成了三个阶段,分别是鼠标左键按下、鼠标移动、鼠标松开三个步骤。如果是鼠标按键刚刚按下,一般只需要记录一下当前的坐标即可。接着在鼠标移动的时候,开始绘制图形。等到最终鼠标左键弹起的时候,绘图结束,所有的shape记录到List当中。

        当然除了绘图之外,另外一部分比较重要的就是菜单的响应,这里建议不同的菜单设置不同的响应函数。虽然麻烦了一点,但是可以保证不出错。

4、详细的代码内容

        最后为了方便学习和交流,这里给出完整的c#代码,中间关于图形绘制的内容多了一点,菜单部分的内容其实还是比较简单的。

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;

namespace WpfApp
{
    public partial class MainWindow : Window
    {
        private Point startPoint;
        private bool isDrawing = false;
        private Shape currentShape;
        private List<Shape> shapes = new List<Shape>();


        // init MainWindow
        public MainWindow()
        {
            InitializeComponent();
        }

        // mouse down function
        private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
        {
            startPoint = e.GetPosition(drawingCanvas);
            isDrawing = true;
        }

        // mouse move function
        private void Canvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (isDrawing)
            {
                Point endPoint = e.GetPosition(drawingCanvas);

                if (currentShape == null)
                {
                    // Determine the shape type based on the selected menu item
                    if (menuItemLine.IsChecked)
                    {
                        currentShape = new Line { Stroke = Brushes.Blue, StrokeThickness = 2 };
                    }
                    else if (menuItemRectangle.IsChecked)
                    {
                        currentShape = new Rectangle { Stroke = Brushes.Red, StrokeThickness = 2, Fill = Brushes.Transparent };
                    }
                    else if(menuItemCircle.IsChecked)
                    {
                        currentShape = new Ellipse { Stroke = Brushes.Green, StrokeThickness = 2, Fill = Brushes.Transparent };
                    }
                    else
                    {
                        currentShape = null;
                        return;
                    }

                    drawingCanvas.Children.Add(currentShape);
                }

                // Update the coordinates of the shape
                if (currentShape is Line line)
                {
                    line.X1 = startPoint.X;
                    line.Y1 = startPoint.Y;
                    line.X2 = endPoint.X;
                    line.Y2 = endPoint.Y;
                }
                else if (currentShape is Rectangle rectangle)
                {
                    double width = endPoint.X - startPoint.X;
                    double height = endPoint.Y - startPoint.Y;

                    rectangle.Width = width > 0 ? width : -width;
                    rectangle.Height = height > 0 ? height : -height;

                    // record first x
                    if(startPoint.X < endPoint.X)
                        Canvas.SetLeft(rectangle, startPoint.X);
                    else
                        Canvas.SetLeft(rectangle, endPoint.X);

                    // record first y
                    if(startPoint.Y < endPoint.Y)
                        Canvas.SetTop(rectangle, startPoint.Y);
                    else
                        Canvas.SetTop(rectangle, endPoint.Y);
                }
                else if(currentShape is Ellipse ecllipse)
                {
                    double width = endPoint.X - startPoint.X;
                    double height = endPoint.Y - startPoint.Y;

                    ecllipse.Width = width > 0 ? width : -width;
                    ecllipse.Height = height > 0 ? height : -height;

                    // judge ecllipse width and height
                    if(ecllipse.Width > ecllipse.Height)
                    {
                        ecllipse.Height = ecllipse.Width;
                    }
                    else
                    {
                        ecllipse.Width = ecllipse.Height;
                    }

                    // record first x
                    if (startPoint.X < endPoint.X)
                        Canvas.SetLeft(ecllipse, startPoint.X);
                    else
                        Canvas.SetLeft(ecllipse, endPoint.X);

                    // record first y
                    if (startPoint.Y < endPoint.Y)
                        Canvas.SetTop(ecllipse, startPoint.Y);
                    else
                        Canvas.SetTop(ecllipse, endPoint.Y);
                }
                else
                {
                    return;
                }
            }
        }

        // mouse up function
        private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
        {
            isDrawing = false;

            if (null != currentShape)
            {
                shapes.Add(currentShape);
                currentShape = null;
            }
        }

        // sub menu function
        private void MenuItemLine_Checked(object sender, RoutedEventArgs e)
        {
            menuItemLine.IsChecked = true;
            menuItemRectangle.IsChecked = false;
            menuItemCircle.IsChecked = false;
        }

        // sub menu function
        private void MenuItemRectangle_Checked(object sender, RoutedEventArgs e)
        {
            menuItemLine.IsChecked = false;
            menuItemRectangle.IsChecked = true;
            menuItemCircle.IsChecked = false;
        }

        // sub menu function
        private void MenuItemCircle_Checked(object sender, RoutedEventArgs e)
        {
            menuItemLine.IsChecked = false;
            menuItemRectangle.IsChecked = false;
            menuItemCircle.IsChecked = true;
        }
    }
}

5、结束彩蛋部分

        另外建议大家可以多使用类似chatgpt的工具来学习c# wpf,这样你给它提示关键字,通过不断的交流,最终一定可以实现你想要的效果。这比单纯的搜索引擎学习效率要高得多。

猜你喜欢

转载自blog.csdn.net/feixiaoxing/article/details/134959411