WInForm —— 自定义画板

项目模板:要实现在背景和无背景上完成画线,画直线、矩形、椭圆、并能随意调整字体的大小

 首先要定义绘制的类型

enum DrawMode
{
    None, // 没有选择绘制型
    Pen,  // 画笔 画直线
    Line,// 画直线
    Rectangle,// 画矩形
    Ellipse, // 画椭圆
    Rubber  // 橡皮擦
}

//如果要想绘制成图片可以使用picturebox作为载体,
//之前使用g.drawLine只是绘制到窗体,只是表面现象,并没有绘制成图片
//把绘制的效果形成一个图片使用drawImage方法

全局变量:

 Graphics g;  //绘制对象
 Graphics imgGra;// 把绘制出效果形成一个图片
 Color curColor = Color.Black;//设置画笔的颜色
 int penSize = 0;// 笔刷粗细
 string title; // 窗体的标题
 DrawMode curMode = DrawMode.None;//当前绘制的类型
 Image backImg;// 背景图片

设置下拉选项

 g = this.CreateGraphics();
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
 toolStripComboBox1.SelectedIndex = 1; //设置下拉框默认值选择
 this.Text = "画板";

 选择背景

private void 选择文件ToolStripMenuItem_Click(object sender, EventArgs e)
{
    OpenFileDialog ofd = new OpenFileDialog();// 文本选择对话框
    ofd.Filter = "png图片|*.png|jpg图片|*.jpg"; //过滤文件类型
    ofd.Multiselect = false;//是否支持多选,
    if (ofd.ShowDialog() == DialogResult.OK)
    {
        Image sourceImage =  Image.FromFile(ofd.FileName);// 加载对应路径的资源 把图片绘制的背景
        //this.ClientRectangle.Width窗体的宽度
        //this.ClientRectangle.Height窗体的高度
        backImg = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);//设置背景图片大小
        imgGra = Graphics.FromImage(backImg);// 把backImage作为绘制背景图

        // 把图片绘制到管理背景图的图像上imgGra
        //imgGra.DrawImage()

        g.Clear(Color.White); //把绘制区域以白色填充,目的先把之前的背景清空掉
        g.DrawImage(sourceImage, this.ClientRectangle);// 绘制图片,参数1是绘制的图片 参数2是绘制的区域
        
        this.Text = title + "\t" + ofd.FileName;
    }

}

无背景

private void 无背景ToolStripMenuItem_Click(object sender, EventArgs e)
{
    // 设置无背景的背景图宽度和高度
    backImg = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height); //设置一张图片
    imgGra = Graphics.FromImage(backImg);// 把图片作为绘制的背景
    imgGra.Clear(Color.White); // 清空背景
    g.DrawImage(backImg, this.ClientRectangle);//绘制图片
    this.Text = title + "\t" + "未命名";

}

点击画笔pen的事件

private void toolStripLabel2_Click(object sender, EventArgs e)
{
    //只是修改绘制的类型,真正绘制的时候在鼠标移动方法进行绘制
    curMode = DrawMode.Pen;
}

鼠标按下事件

 Point startPoint; // 起始点位置
 bool drawFlag;// 控制是否开始绘制的变量

private void Form1_MouseDown(object sender, MouseEventArgs e)
{
    if(e.Button == MouseButtons.Left)
    {
        startPoint = e.Location;// 把点击点坐标赋值给起始点
        drawFlag = true;
    }

}

 鼠标移动

private void Form1_MouseMove(object sender, MouseEventArgs e)
{
    if (drawFlag == false) return;
    switch (curMode) {
    
        case DrawMode.None: 

            break;
        case DrawMode.Pen:
            // 粗细不要写定值 先写2
            g.DrawLine(new Pen(curColor, penSize), startPoint, e.Location);
            imgGra.DrawLine(new Pen(curColor, penSize), startPoint, e.Location);
            startPoint = e.Location;
            break;
        case DrawMode.Line:
            // 为了解决窗体最小化的时候出现 绘制的效果的消失的问题,
            //打开窗体重新调用绘制的方法,把backimage重新绘制到窗体上
            // 给窗体添加一个paint事件 把backimage重新绘制到窗体上
            Form1_Paint(null, null);
            g.DrawLine(new Pen(curColor, penSize), startPoint, e.Location);
           
            break;
        case DrawMode.Rectangle:
            Form1_Paint(null, null);
            g.DrawRectangle(new Pen(curColor, penSize), startPoint.X, startPoint.Y, e.Location.X - startPoint.X, e.Location.Y - startPoint.Y);
            break;
        case DrawMode.Ellipse:
            Form1_Paint(null, null);
            g.DrawEllipse(new Pen(curColor, penSize), startPoint.X, startPoint.Y, e.Location.X - startPoint.X, e.Location.Y - startPoint.Y);
            break;
        case DrawMode.Rubber:
            // 绘制一个白色的线就行
            g.DrawLine(new Pen(Color.White, 10), startPoint, e.Location);
            imgGra.DrawLine(new Pen(Color.White, 10), startPoint, e.Location);
            startPoint = e.Location;
            break;
        default: 
            break;
    
    }

}

鼠标松开

 private void Form1_MouseUp(object sender, MouseEventArgs e)
 {
     drawFlag = false;
     switch (curMode)
     {

         case DrawMode.None:
             break;
         case DrawMode.Pen:
             break;
         case DrawMode.Line:
             imgGra.DrawLine(new Pen(curColor, penSize), startPoint, e.Location);  
             break;
         case DrawMode.Rectangle:
             imgGra.DrawRectangle(new Pen(curColor, penSize), startPoint.X, startPoint.Y, e.Location.X - startPoint.X, e.Location.Y - startPoint.Y);
             break;
         case DrawMode.Ellipse:
           imgGra.DrawEllipse(new Pen(curColor, penSize), startPoint.X, startPoint.Y, e.Location.X - startPoint.X, e.Location.Y - startPoint.Y);
             break;
         case DrawMode.Rubber:
             break;
         default:
             break;

     }

 }

 修改笔刷的颜色

private void 颜色ToolStripMenuItem_Click(object sender, EventArgs e)
{
    //FontDialog
    ColorDialog cd = new ColorDialog();
    if (cd.ShowDialog() == DialogResult.OK)
    {
        curColor = cd.Color; //修改画笔颜色变量
    }

}

修改笔刷大小的事件

private void toolStripComboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    penSize = Convert.ToInt16( toolStripComboBox1.Text);
}
修改绘制类型
private void toolStripLabel3_Click(object sender, EventArgs e)
{
     curMode = DrawMode.Line; //绘制直线
}
矩形
private void toolStripLabel4_Click(object sender, EventArgs e)
{
    //矩形
    curMode = DrawMode.Rectangle;
}
椭圆
private void toolStripLabel5_Click(object sender, EventArgs e)
{
    curMode = DrawMode.Ellipse;//椭圆
}

在改事件中重新绘制图片

private void Form1_Paint(object sender, PaintEventArgs e)
{
    if (backImg == null)
    {
      
        return;
    }
    g.DrawImage(backImg, this.ClientRectangle);

}
private void toolStripLabel6_Click(object sender, EventArgs e)
{
    curMode = DrawMode.Rubber;//
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】进程的优先级及linux下进程的调度于切换

目录 ​编辑 1.优先级是什么 2.linux中的优先级是怎么实现的 ps -la 命令查看当前用户启动的进程​编辑 linux下调整优先级: ①先top一下 ②点击r ③需要输入进程的pid ④回车 ​编辑 ⑤输入想将优秀级修改的值: linux进程优先级范围为什么必须是【60,9…

Navicat的安装与破解

个人介绍 hello hello~ ,这里是 code袁~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 🦁作者简介:一名喜欢分享和记录学习的…

《系统分析与设计》实验-----需求规格说明书 哈尔滨理工大学

文章目录 需求规格说明书1.引言1.1编写目的1.2项目背景1.3定义1.4参考资料 2.任务概述2.1目标2.2运行环境2.3条件与限制 3.数据描述3.1静态数据3.2动态数据3.3数据库介绍3.4数据词典3.5数据采集 4.功能需求4.1功能划分4.2功能描述…

Java——封装、访问修饰符、包

目录 一.封装的概念 二.访问限定符 三.封装扩展之包 1.包的概念 2.导入包中的类 3.自定义包 4.包的访问权限控制举例 5.常见的包 一.封装的概念 面向对象程序三大特性:封装、继承、多态。而类和对象阶段,主要研究的就是封装特性。何为封装呢&am…

linux进阶篇:文件查找的利器——grep命令+管道操作详解

Linux文件查找的利器——grep命令管道操作详解 1 grep简介 grep (global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。 Uni…

Java面试八股文(更新中emsp;)(❤❤)

Java面试八股文 一. 基础篇1. Java语言特点2. 面向对象和面向过程的区别3. 八种基本数据类型的大小,以及他们的封装类4. 标识符的命名规则5. instanceof 关键字的作用6. Java自动装箱与拆箱面试题1: 以下代码会输出什么?面试题2:以…

Linux 网络测速

1.开发背景 网络测速,为了测试开发板的网络速度是否达标的通用测试方法 2.开发需求 搭建 iperf3 ,在 ubuntu 下安装服务端,在板卡上安装客户端,服务端和客户端互发 3.开发环境 ubuntu20.04 嵌入式开发板(debian 千…

用c++实现串匹配问题、选择排序

5.2.2 串匹配问题 【问题】 给定两个字符串S和T,在主串S中查找子串T的过程称为串匹配(string matching,也称模式匹配),T称为模式。在文本处理系统、操作系统、编译系统、数据库系统以及 Internet 信息检索系统中,串匹配是使用最频…

记录flume运行时报NullPointerException异常

【背景说明】 我要起一个将kafka上的topic_log主题中的数据上传到hdfs上的flume进程。 这是我的flume配置文件脚本: #定义组件 a1.sourcesr1 a1.channelsc1 a1.sinksk1#配置source1 a1.sources.r1.type org.apache.flume.source.kafka.KafkaSource a1.sources.r…

JAVA基础06-面向对象,构造器,递归以及对象创建时内存分析(内含代码与练习)

面向对象的概念以及特征 概念 实质上将 "数据" 与 "行为" 的过程, 以类的形式封装起来, 一切以对象为中心语言。 面向对象的程序设计过程中有两个重要概念:类(class)和对象(也称为实例)。 其中…

YOLO-World——S

文章目录 Abstract成果 MethodPre-training Formulation: Region-Text PairsModel ArchitectureYOLO DetectorText EncoderText Contrastive HeadTraining with Online VocabularyInference with Offline Vocabulary Re-parameterizable Vision-Language PANText-guided CSPLay…

强烈推荐 ——电脑终端管理系统

强烈推荐!电脑终端管理系统 电脑终端管理系统使用的目的是为了管控电脑上硬件和软件资产,以及员工使用电脑的行为,最终目的是为了保护企业资产和信息,以下是一些推荐的电脑终端管理系统,这些系统为企业提供了强大的功…

C语言基础入门案例(2)

目录 第一题:编写一个基于switch语句的等级评估程序 第二题:学生成绩评定 第三题:计算圆的周长和面积 第四题:将三个整数按从大到小顺序输出 第五题:打印九九乘法表 第一题:编写一个基于switch语句的等…

TXT文本批量高效编辑,支持给文章结尾进行添加上相同的结语,轻松应对多个文本

在信息爆炸的时代,我们每天面对大量的文本信息,无论是工作文档、新闻稿件还是社交媒体内容,都需要进行高效、精准的编辑。而XT文本批量编辑器正是您理想的助手,它支持批量高效编辑,更能在文章结尾添加上您想要的相同结…

Knowledge Editing for Large Language Models: A Survey

目录 IntroductionProblem Formulation评估指标Methods数据集应用讨论挑战未来方向 大型语言模型(LLMS)最近由于其出色的理解,分析和生成文本的能力而根据其广泛的知识和推理能力来改变了学术和工业景观。然而,LLM的一个主要缺点是…

韩顺平Java | C25 JDBC和连接池(上)

概述 JDBC概述:JDBC为访问不同数据库提供统一接口,为使用者屏蔽细节问题。Java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统,从而完成对数据库的各种操作。 // 模拟代码 //JdbcInterface.java --Java规定的JDBC接口(方法) p…

计算机网络——抓取icmp包

前言 本博客是博主用于记录计算机网络实验的博客,如果疏忽出现错误,还望各位指正。 抓包 我们是用Wireshark工具来进行抓包的。 ​在安装时候一路打勾安装即可,不过最后那个因为是英文,一定要看清,点了立即重启&am…

采用C#.Net +JavaScript 开发的云LIS系统源码 二级医院应用案例有演示

采用C#.Net JavaScript 开发的云LIS系统源码 二级医院应用案例有演示 一、系统简介 云LIS是为区域医疗提供临床实验室信息服务的计算机应用程序,可协助区域内所有临床实验室相互协调并完成日常检验工作,对区域内的检验数据进行集中管理和共享&#xff0…

【UE5.1】使用MySQL and MariaDB Integration插件——(2)查询

在上一篇(【UE5.1】使用MySQL and MariaDB Integration插件——(1)连接MySQL)基础上继续实现查询MySQL数据表功能。 效果 步骤 1. 这里先新建一个控件蓝图,命名为“WBP_OperateDB”,该界面用于在连接数据…

Java——线程

程序 为实现某些功能,使用计算机语言编写的一系列指令(代码)的集合 特指静态的,安装在硬盘中的代码集合 进程 运行中的程序(被加载到内存中),是操作系统进行资源分配的最小单位 线程 进程可以进一步细化为线程,是进程内一个…