AE开发入门20210430之画线、事件代理、创建画笔、画矩形、画椭圆、绘制圆弧、静态类、常见窗体控件

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MyPicture
{
    public partial class UserControl1 : UserControl
    {
        private PictureBox _picBox = new PictureBox();
        private int _drawMode;
        private int x1, x2, y1, y2;
        private int _clickNumber = 0;
        private Graphics _g;
        private Pen _pen;
        public UserControl1(ref PictureBox pic)//修改构造函数,因为要在外部的pictureBox进行绘制,需要将外部的PictureBox传进来,通过址传递的方式,传进来。
                                               //查参数传递的几种类别
        {
            InitializeComponent();
            //初始化,也可以在load里面给它
            this._picBox = pic;
        }
        private void UserControl1_Load(object sender, EventArgs e)
        {
            //给它加上事件代理
            this.PicBox.MouseDown += PicBox_MouseDown;//先写上+=,按两次tab键即可
                                                      //把代理名称自动加入,自动生成代理函数
            this._g = this.PicBox.CreateGraphics();//在对应的pictureBox上进行绘制
            this._pen = new Pen(Color.Red, 3);//创建pen,需要new,可以设置颜色和宽度
            //查color静态类
            this._picBox.MouseUp += _picBox_MouseUp;
        }

        private void _picBox_MouseUp(object sender, MouseEventArgs e)
        {
            //throw new NotImplementedException();
            //需要判定,_drawMode是什么状态
            if (_drawMode == 2)
            {
                x2 = e.X;
                y2 = e.Y;
                //int width = x2 - x1;
                //if (width < 0)
                //    width = -width;
                int width = Math.Abs(x1 - x2);//与上面三行作用一致
                int heighth = Math.Abs(y1 - y2);
                //查math静态类

                //加上判定
                if(x1<x2&&y1<y2)
                _g.DrawRectangle(_pen, x1, y1, width, heighth);
                else if(x1 < x2 && y1 >y2)
                _g.DrawRectangle(_pen, x1, y2, width, heighth);
                else if (x1 > x2 && y1 > y2)
                    _g.DrawRectangle(_pen, x2, y2, width, heighth);
                else if (x1 > x2 && y1 < y2)
                    _g.DrawRectangle(_pen, x1, y1, width, heighth);
            //作业:把当前控件向外拓展,注意x y 取值
            }

        }

        private void PicBox_MouseDown(object sender, MouseEventArgs e)//MouseEventArgs是存放鼠标的响应函数
        {
            //throw new NotImplementedException();
            if (this._drawMode == 1 && this._clickNumber != 0)
            {
                //需要记录点击的次数,所以需要定义新的变量,
                //需要把新的坐标取下来;
                x2 = e.X;
                y2 = e.Y;
                //创建profic对象,有相应的DrawLine等绘制的方法
                //Graphics g= this._picBox.CreateGraphics();
                //g.DrawLine(x2,y2);//第一个参数要是一个pen(画笔),第二个参数是一个点,第三个参数是一个点
                需要创建pen,,每次要Mosedown的时候,每次都要创建一次,每次之间没有关系,为避免此现象,我们要提前做一个字段
                ///
                this._g.DrawLine(this._pen, x1, y1, x2, y2);//设置参数,需要给画笔,和两个点
                x1 = x2;
                y1 = y2;

            }
            else//_clickNumber=0说明没点击
            {
                //谁保存鼠标的位置? MouseEventArgs e里的e
                x1 = e.X;
                y1 = e.Y;
            }
            this._clickNumber++;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.DrawMode = 2;
            this._clickNumber = 0;
            //画矩形,确定两个点,起始点,对角点,down的时候有一个点,up的时候一个点,所以需要加一个UP的响应函数
        }
        public PictureBox PicBox { get => _picBox; set => _picBox = value; }
        public int DrawMode { get => _drawMode; set => _drawMode = value; }
        private void button1_Click(object sender, EventArgs e)
        {
            //想有一个变量,记得我想,下面我想画线了,可以存一个字段,然后知道我们点击了哪一个按钮,想进行什么操作
            this.DrawMode = 1;
            //画线需要PictureBOx,去定义
            //连线的时候需要坐标记忆,记下第一个点 第二个点,连起来,再把第二个点坐标给第一个点,用第二个点记录下一个点
            //什么时候开始mos down ,这个响应函数在哪里,怎么加,什么时候加,事件代理,什么时候把代理关系建立起来
            //控件一加载,激发他的load函数,建立关联
            this._clickNumber = 0;//第一次点击是激发
        }
    }
}



        }

画线

 private void button1_Click(object sender, EventArgs e)
        {
            //想有一个变量,记得我想,下面我想画线了,可以存一个字段,然后知道我们点击了哪一个按钮,想进行什么操作
            this.DrawMode = 1;
            //画线需要PictureBOx,去定义
            //连线的时候需要坐标记忆,记下第一个点 第二个点,连起来,再把第二个点坐标给第一个点,用第二个点记录下一个点
            //什么时候开始mos down ,这个响应函数在哪里,怎么加,什么时候加,事件代理,什么时候把代理关系建立起来
            //控件一加载,激发他的load函数,建立关联
            this._clickNumber = 0;//第一次点击是激发
        }

1.双击按钮。进入button1_Click。
2.需要有一个变量,记录的是,是否要进行画线操作。
即:可以存一个字符,知道我们点击了哪一个按钮,进行什么操作。
也就是:

this.DrawMode = 1;

这里就是,当DrawMode=1的时候,进行画线操作。
3.又因为画线的时候需要进行坐标的记忆,记下第一个点,第二个点,连起来,再把第二个点坐标给第一个点,用第二个点记录下一个点。
4.什么时候开始画呢?响应函数在哪里呢?什么时候加?
事件代理的想法。那么什么时候把代理关系建立起来。控件一旦加载,就会激发load函数,建立起关联。
这里,我们用_clickNumber记录点击的次数。

private void UserControl1_Load(object sender, EventArgs e)
        {
            //给它加上事件代理
            this.PicBox.MouseDown += PicBox_MouseDown;//先写上+=,按两次tab键即可
                                                      //把代理名称自动加入,自动生成代理函数
            this._g = this.PicBox.CreateGraphics();//在对应的pictureBox上进行绘制
            this._pen = new Pen(Color.Red, 3);//创建pen,需要new,可以设置颜色和宽度
            //查color静态类
            this._picBox.MouseUp += _picBox_MouseUp;
        }

5.画线需要PictureBox,需要进行创建,于是我们可以修改构造函数进行创建。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MyPicture
{
    public partial class UserControl1 : UserControl
    {
        private PictureBox _picBox = new PictureBox();
        private int _drawMode;
        private int x1, x2, y1, y2;
        private int _clickNumber = 0;
        private Graphics _g;//绘图
        private Pen _pen;
        public UserControl1(ref PictureBox pic)
//修改构造函数,因为要在外部的pictureBox进行绘制,需要将外部的PictureBox传进来,通过址传递的方式,传进来。
//查参数传递的几种类别。
        {
            InitializeComponent();
            //初始化,也可以在load里面给它
            this._picBox = pic;
        }
        、
        、
        、
   	}
}

ref out 值传递 引用传递

https://blog.csdn.net/m0_37679113/article/details/83045813

ref的定义

通过引用来传递参数。
ref也是Reference的缩写。了解了定义之后,ref怎么用呢?首先我们要明白值类型和引用类型的概念。这里的ref基本上就是服务于值类型的。

//不使用 ref;
void Method(int myRefInt)
{
    myRefInt += 66;
}

int number = 1;
Method(number);
Console.WriteLine(number);
**//输出 : 1;**

//使用ref
void Method(ref int myRefInt)
{
    myRefInt += 66;
}

int number = 1;
Method(ref number);
Console.WriteLine(number);

**//输出:67**

使用ref的时候,函数Method(ref int myRefInt)值收到的是number的地址,函数中执行的myRefInt+=66;此时相当于number+=66;直接修改了number地址的值。
那就可以等处结论了:
ref是通过给方法传递值类型的参数,直接操作同一个变量的关键字。

out的定义

“out”作为一个参数修饰符,允许您通过引用而不是通过值将参数传递给方法。

在接口和委托的泛型类型参数声明中,它指定类型参数是协变的。

今天的语境下,我们只讨论第一种作为引用传递参数的定义。

int number;

Method(number);

void Method(int myRefInt)
{
    myRefInt = 66;
}

Console.WriteLine(number);
//输出:0

int number;

Method(out number);

void Method(out int myRefInt)
{
    myRefInt = 66;
}

Console.WriteLine(number);
//输出:66

out和ref其实都可以允许通过引用来传递参数。

那么问题来了既然ref 、out的作用看起来一样,为什么还定义了两个关键字呢?

当你在使用ref传递参数的时候,ref修饰的参数必须要有值,但是out可以使用一个未赋值的变量作为参数传递。

out应该是在方法内部做了分配地址的操作,然后把地址赋给外部的变量。但是ref的话是直接传递外部地址进方法。

值传递与引用传递

   对于值类型来说,栈中存储的是直接使用的数据
   对于引用类型来说,栈中存储的是堆中对象的地址
   
   对于值传递,传递的是栈中保存的数据
   对于引用传递,传递的是栈本身的地址
class Program
{
    static void Main(string[] args)
    {
        //引用类型的赋值,只是赋值了对象在堆中的地址
        Person p = new Person();   //声明的一个Person类,包含有Name属性
        p.Name = "yzk";
        D2(p);
        Console.WriteLine(p.Name);   //返回值为jk
 
        //值类型的赋值,赋值了具体的值,而不是地址
        int n = 10;
        D1(n);
        Console.WriteLine(n);       //返回值为10
        Console.ReadKey();
    }
    //值类型的值传递
    static void D1(int m)
    {
        m = m + 1;
    }
    //引用类型的值传递
    static void D2(Person p1)
    {
        p1.Name = "jk";
    }
}

加事件代理

 private void UserControl1_Load(object sender, EventArgs e)
        {
            //给它加上事件代理
            this.PicBox.MouseDown += PicBox_MouseDown;//先写上+=,按两次tab键即可
                                                      //把代理名称自动加入,自动生成代理函数
            this._g = this.PicBox.CreateGraphics();//在对应的pictureBox上进行绘制
            this._pen = new Pen(Color.Red, 3);//创建pen,需要new,可以设置颜色和宽度
            //查color静态类
            this._picBox.MouseUp += _picBox_MouseUp;
        }

创建画笔

https://blog.csdn.net/gy0124/article/details/107082190
https://blog.csdn.net/haoduo123456789001/article/details/51545328/

 this._pen = new Pen(Color.Red, 3);//创建pen,需要new,可以设置颜色和宽度

画矩形

private void button2_Click(object sender, EventArgs e)
        {
            this.DrawMode = 2;
            this._clickNumber = 0;
            //画矩形,确定两个点,起始点,对角点,down的时候有一个点,up的时候一个点,所以需要加一个UP的响应函数
        }

1.DrawMode=2的时候,进行画矩形的操作。
2.确定第一次点击是激发。

this._clickNumber = 0;//第一次点击是激发

3.画矩形,确定两个点,起始点,对角点,鼠标down的时候有一个点,up的时候一个点,所以需要加一个UP的响应函数

 private void _picBox_MouseUp(object sender, MouseEventArgs e)
        {
            //throw new NotImplementedException();
            //需要判定,_drawMode是什么状态
            if (_drawMode == 2)
            {
                x2 = e.X;
                y2 = e.Y;
                //int width = x2 - x1;
                //if (width < 0)
                //    width = -width;
                int width = Math.Abs(x1 - x2);//与上面三行作用一致
                int heighth = Math.Abs(y1 - y2);
                //查math静态类

                //加上判定
                if(x1<x2&&y1<y2)
                _g.DrawRectangle(_pen, x1, y1, width, heighth);
                else if(x1 < x2 && y1 >y2)
                _g.DrawRectangle(_pen, x1, y2, width, heighth);
                else if (x1 > x2 && y1 > y2)
                    _g.DrawRectangle(_pen, x2, y2, width, heighth);
                else if (x1 > x2 && y1 < y2)
                    _g.DrawRectangle(_pen, x1, y1, width, heighth);
            //作业:把当前控件向外拓展,注意x y 取值
            }

        }

还需要一个down函数。

 private void PicBox_MouseDown(object sender, MouseEventArgs e)//MouseEventArgs是存放鼠标的响应函数
        {
            //throw new NotImplementedException();
            if (this._drawMode == 1 && this._clickNumber != 0)
            {
                //需要记录点击的次数,所以需要定义新的变量,
                //需要把新的坐标取下来;
                x2 = e.X;
                y2 = e.Y;
                //创建Graphics
对象,有相应的DrawLine等绘制的方法
                //Graphics g= this._picBox.CreateGraphics();
                //g.DrawLine(x2,y2);//第一个参数要是一个pen(画笔),第二个参数是一个点,第三个参数是一个点
                需要创建pen,,每次要Mosedown的时候,每次都要创建一次,每次之间没有关系,为避免此现象,我们要提前做一个字段
                ///
                this._g.DrawLine(this._pen, x1, y1, x2, y2);//设置参数,需要给画笔,和两个点
                x1 = x2;
                y1 = y2;

            }
            else//_clickNumber=0说明没点击
            {
                //谁保存鼠标的位置? MouseEventArgs e里的e
                x1 = e.X;
                y1 = e.Y;
            }
            this._clickNumber++;
        }

4.创建Graphics

 private void PicBox_MouseDown(object sender, MouseEventArgs e)//MouseEventArgs是存放鼠标的响应函数
        {
            //throw new NotImplementedException();
            if (this._drawMode == 1 && this._clickNumber != 0)
            {
                //需要记录点击的次数,所以需要定义新的变量,
                //需要把新的坐标取下来;
                x2 = e.X;
                y2 = e.Y;
                //创建Graphics对象,有相应的DrawLine等绘制的方法
                //Graphics g= this._picBox.CreateGraphics();
                //g.DrawLine(x2,y2);//第一个参数要是一个pen(画笔),第二个参数是一个点,第三个参数是一个点
                需要创建pen,,每次要Mosedown的时候,每次都要创建一次,每次之间没有关系,为避免此现象,我们要提前做一个字段
                ///
                this._g.DrawLine(this._pen, x1, y1, x2, y2);//设置参数,需要给画笔,和两个点
                x1 = x2;
                y1 = y2;

            }
            else//_clickNumber=0说明没点击
            {
                //谁保存鼠标的位置? MouseEventArgs e里的e
                x1 = e.X;
                y1 = e.Y;
            }
            this._clickNumber++;
        }

DrawEllipse画椭圆

https://blog.csdn.net/htqlhy/article/details/3847601
https://blog.csdn.net/jiangqin115/article/details/104786211/

注意:我们可以发现把鼠标放在函数名上的时候,会出现对这个函数的一些解释,我们可以通过这个解释进行编写代码。

  g.DrawEllipse(p, 10, 10, 100, 100);//在画板上画椭圆,起始坐标为(10,10),外接矩形的宽为,高为

在这里插入图片描述

drawArc方法:绘制圆弧

https://blog.csdn.net/Gou_Hailong/article/details/106715943
https://blog.csdn.net/zzldm/article/details/53426345
https://blog.csdn.net/Gou_Hailong/article/details/106715943

public void drawArc (RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)

参数说明

oval:圆弧所在的椭圆对象。

startAngle:圆弧的起始角度。

sweepAngle:圆弧的角度。

useCenter:是否显示半径连线,true表示显示圆弧与圆心的半径连线,false表示不显示。

paint:绘制时所使用的画笔。

math静态类

https://tsov.net/uupee/9075/
https://blog.csdn.net/a1256242238/article/details/72821659

1.Math.Abs 已重载。返回指定数字的绝对值。
2.Math.Acos 返回余弦值为指定数字的角度。
3.Math.Asin 返回正弦值为指定数字的角度。
4.Math.Atan 返回正切值为指定数字的角度。
5.Math.Atan2 返回正切值为两个指定数字的商的角度。
6.Math.BigMul 生成两个 32 位数字的完整乘积。
7.Math.Ceiling 已重载。 返回大于或等于指定数字的最小整数。
8.Math.Cos 返回指定角度的余弦值。
9.Math.Cosh 返回指定角度的双曲余弦值。
10.Math.DivRem 已重载。 计算两个数字的商,并在输出参数中返回余数。
11.Math.Equals 已重载。 确定两个 Object 实例是否相等。 (从 Object 继承。)
12.Math.Exp 返回 e 的指定次幂。
13.Math.Floor 已重载。 返回小于或等于指定数字的最大整数。
14.Math.GetHashCode 用作特定类型的哈希函数。GetHashCode 适合在哈希算法和数据结构(如哈希表)中使用。 (从 Object 继承。)
15.Math.GetType 获取当前实例的 Type。 (从 Object 继承。)
16.Math.IEEERemainder 返回一指定数字被另一指定数字相除的余数。
17.Math.Log 已重载。 返回指定数字的对数。
18.Math.Log10 返回指定数字以 10 为底的对数。
19.Math.Max 已重载。 返回两个指定数字中较大的一个。
20.Math.Min 已重载。 返回两个数字中较小的一个。
21.Math.Pow 返回指定数字的指定次幂。
22.Math.ReferenceEquals 确定指定的 Object 实例是否是相同的实例。 (从 Object 继承。)
23.Math.Round 已重载。 将值舍入到最接近的整数或指定的小数位数。
24.Math.Sign 已重载。 返回表示数字符号的值。
25.Math.Sin 返回指定角度的正弦值。
26.Math.Sinh 返回指定角度的双曲正弦值。
27.Math.Sqrt 返回指定数字的平方根。
28.Math.Tan 返回指定角度的正切值。
29.Math.Tanh 返回指定角度的双曲正切值。
30.Math.ToString 返回表示当前 Object 的 String。 (从 Object 继承。)
31.Math.Truncate 已重载。 计算一个数字的整数部分。

常见窗体控件

https://blog.csdn.net/Gou_Hailong/article/details/106663543

常见问题

1.在自己制作控件的时候,可能会出现找不到pictureBox1,但将其加入到窗体应用中后,我们会发现,拖入一个PictureBox后,会解决此问题,原因在于,构造函数中需要传入一个pictureBOx,即拖入pictureBox控件。
2.UP Down函数从哪里来呢?(事件代理函数)

https://blog.csdn.net/weixin_34355715/article/details/94227770

3.在这里插入图片描述
这个问题解决方式:将控件加入到窗体应用程序即可,因为我们将构造函数修改了,只有加入窗体应用,并拖入一个PICtureBOx才可以运行修改后的构造函数

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值