winform绘制PLC串联并联模块demo


这是我个人实现的plc串联并联模块绘制的功能案例,模仿可视化配置PLC功能。能够实现模块绘制以及各模块自适应显示功能。

namespace PLCTest
{
    public partial class Form1 : Form
    {
        private List startPointList = new List();
        private List plcList = new List();

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)//点击鼠标,开始绘制
        {
            if (e.Button == MouseButtons.Left)
            {
                startPointList.Add(e.Location);
                PLCShow plc = new PLCShow(plcList, startPointList);
                plcList.Add(plc);
                this.Invalidate();
            }
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            for (int i = 0; i < startPointList.Count; i++)
            {
                plcList[i].DrawPLC(e.Graphics, startPointList[i], this);
            }
        }

        private void Button1_Click(object sender, EventArgs e)//撤销绘制功能
        {
            if (plcList.Count > 0)
            {
                plcList.RemoveAt(plcList.Count - 1);
                startPointList.RemoveAt(startPointList.Count - 1);
            }            
            this.Invalidate();
        }
    }


    public class PLCShow
    {
        public List ptList = new List();
        private List startPointList;
        private List plcList;

        private bool isSpecial = false;
        //public bool isChanged = false;
        private bool isChangeOther = false;

        public PLCShow(List plcList,List startPointList)
        {
            this.plcList = plcList;
            this.startPointList = startPointList;
        }
        private void CreatNormalPLCPoint(Point pt1)
        {
            ptList.Add(pt1);
            ptList.Add(new Point(pt1.X + 30, pt1.Y));
            ptList.Add(new Point(pt1.X + 30, pt1.Y - 10));
            ptList.Add(new Point(pt1.X + 30, pt1.Y + 10));
            ptList.Add(new Point(pt1.X + 38, pt1.Y - 10));
            ptList.Add(new Point(pt1.X + 38, pt1.Y + 10));
            ptList.Add(new Point(pt1.X + 38, pt1.Y));
            ptList.Add(new Point(pt1.X + 68, pt1.Y));
        }
        private void CreatSpecialPLCPoint(Point pt1)
        {
            ptList.Add(pt1);
            ptList.Add(new Point(pt1.X, pt1.Y + 35));
            ptList.Add(new Point(pt1.X + 30, pt1.Y + 35));
            ptList.Add(new Point(pt1.X + 30, pt1.Y + 25));
            ptList.Add(new Point(pt1.X + 30, pt1.Y + 45));
            ptList.Add(new Point(pt1.X + 38, pt1.Y + 25));
            ptList.Add(new Point(pt1.X + 38, pt1.Y + 45));
            ptList.Add(new Point(pt1.X + 38, pt1.Y + 35));
            ptList.Add(new Point(pt1.X + 68, pt1.Y + 35));
            ptList.Add(new Point(pt1.X + 68, pt1.Y));
        }
        public void DrawPLC(Graphics g, Point pt, Form1 form)
        {
            if (this == plcList[plcList.Count - 1] && isChangeOther==false)//绘制的是当前按下的PLC模块
            {
                for (int i = 0; i < startPointList.Count - 1; i++)
                {
                    if (plcList[i].isSpecial == false)//在串联模块附近
                    {
                        int offsetX = plcList[i].ptList[7].X - pt.X;
                        int offsetY = plcList[i].ptList[7].Y - pt.Y;
                        if (Math.Abs(offsetX) <= 20 && Math.Abs(offsetY) <= 10)//7号点附近,创建串联模块
                        {
                            CreatNormalPLCPoint(plcList[i].ptList[7]);
                            DrawNormal(g);
                            break;
                        }
                        //创建并联模块
                        if (plcList[i].ptList[2].X - 10 < pt.X && plcList[i].ptList[4].X + 10 > pt.X && plcList[i].ptList[2].Y - 10 < pt.Y && plcList[i].ptList[3].Y + 10 > pt.Y)
                        {
                            CreatSpecialPLCPoint(plcList[i].ptList[0]);
                            DrawSpecial(g);
                            isSpecial = true;
                            break;
                        }
                    }
                    else//在并联模块附近
                    {
                        int offsetX = plcList[i].ptList[8].X - pt.X;
                        int offsetY = plcList[i].ptList[8].Y - pt.Y;
                        bool firstB = Math.Abs(offsetX) <= 20 && Math.Abs(offsetY) <= 10;//在8号点附近
                        offsetX = plcList[i].ptList[9].X - pt.X;
                        offsetY = plcList[i].ptList[9].Y - pt.Y;
                        bool secondB = offsetX >= 0 && offsetX < 20 && Math.Abs(offsetY) <= 10;//在9号点左侧
                        bool thirdB = offsetX < 0 && offsetX > -20 && Math.Abs(offsetY) <= 10;//在9号点右侧
                        bool fourB = plcList[i].ptList[3].X - 10 < pt.X && plcList[i].ptList[5].X + 10 > pt.X &&
                                     plcList[i].ptList[3].Y - 10 < pt.Y && plcList[i].ptList[4].Y + 10 > pt.Y;
                        if (firstB || secondB)
                        {
                            if (firstB)
                            {
                                CreatNormalPLCPoint(plcList[i].ptList[8]);
                            }
                            if (secondB)
                            {
                                CreatNormalPLCPoint(plcList[i].ptList[9]);
                            }
                            //DrawNormal(g);
                            if (isChangeOther == false)//更改当前并联模块的显示,将8、9号点右移,且多画一条线
                            {
                                plcList[i].ptList[8] = new Point(plcList[i].ptList[8].X + 68, plcList[i].ptList[8].Y);
                                plcList[i].ptList[9] = new Point(plcList[i].ptList[9].X + 68, plcList[i].ptList[9].Y);
                                if (plcList[i].ptList.Count < 11)
                                {
                                    plcList[i].ptList.Add(new Point(plcList[i].ptList[7].X + 30, plcList[i].ptList[7].Y - 35));
                                }
                                //plcList[i].ptList[10] = new Point(plcList[i].ptList[7].X + 30, plcList[i].ptList[7].Y-35);
                                isChangeOther = true;
                                form.Invalidate();
                            }                            
                            break;
                        }
                        if (thirdB)
                        {
                            CreatNormalPLCPoint(plcList[i].ptList[9]);
                            DrawNormal(g);
                            break;
                        }
                        if (fourB)
                        {
                            CreatSpecialPLCPoint(plcList[i].ptList[1]);
                            DrawSpecial(g);
                            isSpecial = true;
                            break;
                        }
                    }
                }
                if (ptList.Count == 0 && plcList.Count == 1)//当前按下点附近都没有PLC模块,且为第一次创建,此时创建新的PLC模块
                {
                    CreatNormalPLCPoint(pt);
                    DrawNormal(g);
                }
                if(ptList.Count == 0 && plcList.Count != 1)//当前按下点附近没有PLC模块,禁止创建
                {
                    plcList.RemoveAt(plcList.Count - 1);
                    startPointList.RemoveAt(plcList.Count - 1);
                }
            }
            else//绘制之前的模块
            {
                if (isSpecial == false)
                {
                    DrawNormal(g);
                }
                else
                {
                    DrawSpecial(g);
                }
            }
        }
        private void DrawNormal(Graphics g)//绘制串联模块
        {
            //AliceBlue
            Pen pen = new Pen(Color.AliceBlue, 2);
            g.DrawLine(pen, ptList[0], ptList[7]);
            pen.Color = Color.Black;
            for (int i = 0; i < 4; i++)
            {
                g.DrawLine(pen, ptList[i*2], ptList[i*2+1]);
            }            
        }
        private void DrawSpecial(Graphics g)//绘制并联模块
        {
            Pen pen = new Pen(Color.AliceBlue, 2);
            g.DrawLine(pen, ptList[1], ptList[8]);
            pen.Color = Color.Black;
            g.DrawLine(pen, ptList[0], ptList[1]);
            g.DrawLine(pen, ptList[1], ptList[2]);
            g.DrawLine(pen, ptList[3], ptList[4]);
            g.DrawLine(pen, ptList[5], ptList[6]);
            g.DrawLine(pen, ptList[7], ptList[8]);
            g.DrawLine(pen, ptList[8], ptList[9]);
            if (ptList.Count >= 11)
            {
                g.DrawLine(pen, ptList[9], ptList[10]);
            }
        }
    }

}

效果图如下: