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

news2024/11/24 3:51:40

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱: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,这样你给它提示关键字,通过不断的交流,最终一定可以实现你想要的效果。这比单纯的搜索引擎学习效率要高得多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1306151.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【flutter对抗】blutter使用+ACTF习题

最新的能很好反编译flutter程序的项目 1、安装 git clone https://github.com/worawit/blutter --depth1​ 然后我直接将对应的两个压缩包下载下来&#xff08;通过浏览器手动下载&#xff09; 不再通过python的代码来下载&#xff0c;之前一直卡在这个地方。 如果读者可以…

C++11 【初识】

C11简介 1.在2003年C标准委员会曾经提交了一份技术勘误表(简称TC1)&#xff0c;使得C03这个名字已经取代了C98称为C11之前的最新C标准名称。 2.不过由于C03(TC1)主要是对C98标准中的漏洞进行修复&#xff0c;语言的核心部分则没有改动&#xff0c;因此人们习惯性的把两个标准合…

【vtkWidgetRepresentation】第十期 vtkAngleRepresentation标注角度

很高兴在雪易的CSDN遇见你 前言 本文分享VTK中的角度标注,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO AngleRepresentation 目录 前言 1. vtkAngleRepresentatio

Windows使用selenium操作浏览器爬虫

以前的大部分程序都是操作Chrome&#xff0c;很少有操作Edge&#xff0c;现在以Edge为例。 Selenium本身是无法直接控制浏览器的&#xff0c;不同的浏览器需要不同的驱动程序&#xff0c;Google Chrome需要安装ChromeDriver、Edge需要安装Microsoft Edge WebDriver&#xff0c…

直面双碳目标,优维科技携手奥意建筑打造绿色低碳建筑数智云平台

优维“双碳”战略合作建筑 为落实创新驱动发展战略&#xff0c;增强深圳工程建设领域科技创新能力&#xff0c;促进技术进步、科技成果转化和推广应用&#xff0c;根据《深圳市工程建设领域科技计划项目管理办法》《深圳市住房和建设局关于组织申报2022年深圳市工程建设领域科…

二叉搜索树基本概念与实现

目录 基本概念 模拟实现 完整代码 基本概念 根的左节点比根小 根的右节点比根大 左右子树都满足 搜索二叉树的中序遍历是升序 模拟实现 完整代码 #pragma oncetemplate<class K> struct BSNode {BSNode<K>* _left;BSNode<K>* _right;K _val;BSNode(c…

【C语言程序设计】循环结构程序设计

目录 前言 一、程序设计第一题 二、程序设计第二题 三、程序设计第三题 总结 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &#x1f4a1;本文由Filotimo__✍️原创&#xff0c;首发于CSDN&#x1f4da…

1.函数递归起(复习)

1.debug版本可以调试,realse版本不能调试 2.在realse版本中,代码已经得到了优化(编译器可能会自作主张地对代码进行优化),在大小和速度上都是最优的 3.ctrl F5 是开始执行不调试 4.设置好断点后,用F5到达该断点,相当于是到达了该断点的那个位置程序就先停止运行了 5.设立断…

Linux shell编程学习笔记35:seq

0 前言 在使用 for 循环语句时&#xff0c;我们经常使用到序列。比如&#xff1a; for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i * 2 $(expr $i \* 2)"; done 其中的 1 2 3 4 5 6 7 8 9 10;就是一个整数序列 。 为了方便我们使用数字序列&#xff0c;Linux提供了…

UDS DTC状态掩码/DTC状态位

文章目录 简介用途依赖知识1、测试&#xff08;test&#xff09;2、操作循环&#xff08;operation cycle&#xff09;3、老化&#xff08;aging&#xff09; DTC状态位1、Bit 0&#xff1a;Test Failed2、Bit 1&#xff1a;Test Failed This operation cycle3、Bit 2&#xff…

【大数据】Hadoop生态未来发展的一些看法

大数据的起源 谷歌在2003到2006年间发表了三篇论文&#xff0c;《MapReduce: Simplified Data Processing on Large Clusters》&#xff0c;《Bigtable: A Distributed Storage System for Structured Data》和《The Google File System》介绍了Google如何对大规模数据进行存储…

基于51单片机的语音识别控制系统

0-演示视频 1-功能说明 &#xff08;1&#xff09;使用DHT11检测温湿度&#xff0c;然后用LCD12864显示&#xff0c;语音播放&#xff0c;使用STC11l08xe控制LD3320做语音识别&#xff0c; &#xff08;2&#xff09;上电时语音提示&#xff1a;欢迎使用声音识别系统&#xf…

数据结构篇-顺序表及单项链表

目录 一、学习目标 二、顺序表 1. 线性表 1.1 概念 1.2 举例 2. 顺序表 2.1 基本概念 2.2 基本操作 2.3 顺序表优缺点总结 三、单项链表 1. 基本概念 2. 链表的分类 无头节点&#xff1a; 有头节点&#xff1a; 增添加节点 查找节点 删除节点 链表遍历 销毁链…

【ARM Trace32(劳特巴赫) 使用介绍 13 -- Trace32 断点 Break 命令篇】

文章目录 1. Break.Set1.1 TRACE32 Break1.1.1 Break命令控制CPU的暂停1.2 Break.Set 设置断点1.2.1 Trace32 程序断点1.2.2 读写断点1.2.2.1 变量被改写为特定值触发halt1.2.2.2 设定非值触发halt1.2.2.4 变量被特定函数改写触发halt1.2.3 使用C/C++语法设置断点条件1.2.4 使用…

折点计数 C语言xdoj46

问题描述 给定n个整数表示一个商店连续n天的销售量。如果某天之前销售量在增长&#xff0c;而后一天销售量减少&#xff0c;则称这一天为折点&#xff0c;反过来如果之前销售量减少而后一天销售量增长&#xff0c;也称这一天为折点&#xff0c;其他的天都不是折点。如图…

AI大模型行业2024年上半年投资策略:大模型多模态化趋势显著,AI应用侧加速繁华

今天分享的AI系列深度研究报告&#xff1a;《AI大模型行业2024年上半年投资策略&#xff1a;大模型多模态化趋势显著&#xff0c;AI应用侧加速繁华》。 &#xff08;报告出品方&#xff1a;东莞证券&#xff09; 报告共计&#xff1a;30页 1.传媒行业行情和业绩回顾 1.1行业…

数据可视化:解析跨行业普及之道

数据可视化作为一种强大的工具&#xff0c;在众多行业中得到了广泛的应用&#xff0c;其价值和优势不断被发掘和利用。今天就让我以这些年来可视化设计的经验&#xff0c;讨论一下数据可视化在各个行业中备受青睐的原因吧。 无论是商业、科学、医疗保健、金融还是教育领域&…

spring 笔记一 spring快速入门和配置文件详解

Spring简介 Spring是分层的 Java SE/EE应用full-stack 轻量级开源框架&#xff0c;以 IoC&#xff08;Inverse Of Control&#xff1a;反转控制&#xff09;和AOP&#xff08;Aspect Oriented Programming&#xff1a;面向切面编程&#xff09;为内核。 提供了展现层SpringMV…

如何FL Studio显示中文?切换语言教程

你是不是也在为fl studio的英文界面而苦恼&#xff1f;你是不是也想让你的fl studio 说中文&#xff0c;方便你制作音乐&#xff1f;你是不是也在网上找了很多教程&#xff0c;却发现都是复杂的&#xff0c;或者已经过时的&#xff1f;如果你的答案是肯定的&#xff0c;那么你来…

c++国际象棋有人机qt5.9.9启动chesss

项目简介&#xff1a; 利用C的知识和QT以及一些自行拓展的新知识&#xff0c;实现国际象棋的开发。 使自己更加深层的理解和掌握c并在程序中展现出来&#xff0c;同时开发编程的思想和能力&#xff0c;以及扩展知识面&#xff0c;学习一些课上没有涉及的内容。同时通过阅读一…