• 图形化控件开发


    最近这段时间,公司需要做一个图形化配置工具。

    主要是有以下一些要求:

    1、针对一些底层的智能设备(智能楼宇的控制器),通过COM口连接上,并通过相关协议读取参数值

    2、支持一些基本的逻辑运算,以及公司业务的一些特性“点”,一种点可以看成一个图形化控件

    3、参数在图形化工具上显示出来,工程人员直接设置图形属性设置参数值、连线等

    4、支持在线和离线2种工作方式,设置好参数后直接在界面上下载到设备里

    5、工作太支持拖动,连线,放大缩小,保存设计文件等

    6、“点”的本身业务要求,略。。。

    经过一番调研,winfrom的图形化控件技术,并没有成熟的框架出来。

    只有一些零碎的demo,大体上的思路是通过重绘来实现具体的图形控件。

    在这里也提一下Netron框架,这个框架代码我看了很多遍,很多思路都从这里来,但是太繁琐了,改动起来非常吃力

    所以我自己重新写了一遍,大体思路没变,只是走精简路线,以下是我们的工具最终的界面样式,

    我打算把每一步都分拆贴出来,做成一个教程。给大家一个参考

    1、新建自定义控件抽象类

    1.1 包含一些基本属性,如字体、是否悬停、是否选中、画布

    1.2 包含几个抽象方法,绘制控件皮肤、移动、悬停判断、重新绘制

        public abstract class AbstractShape
        {
            [Browsable(false)]
            public Font DefaultFont { get; private set; }
    
            [Browsable(false)]
            public Pen DefaultPen { get; private set; }
    
            [Browsable(false)]
            public bool IsHover { get; set; }
    
            [Browsable(false)]
            public bool IsSelected { get; set; }
    
            [Browsable(false)]
            public GraphControl Canvas { get; set; }
    
            public AbstractShape() { }
            public AbstractShape(GraphControl site)
            {
                DefaultFont = new Font("宋体", 10F);
                DefaultPen = new Pen(Brushes.Black, 1F);
                Canvas = site;
                IsHover = false;
                IsSelected = false;
            }
    
            public abstract void Paint(Graphics g);
            public abstract bool Hover(Point p);
            public abstract void Invalidate();
            public abstract void Move(Point p);
        }

    2、绘制一个自定义控件基类

    包含一些基本属性及一些共性方法实现

        public class ShapeBase : AbstractShape
        {
            protected Rectangle RectangleBase;
    
            [Browsable(false)]
            public Brush ShapeBrush { get; protected set; }
    
            [Browsable(true), Description("Width"), Category("Layout")]
            public int Width
            {
                get { return this.RectangleBase.Width; }
                set { Resize(value, this.Height); }
            }
    
            [Browsable(true), Description("Height"), Category("Layout")]
            public int Height
            {
                get { return this.RectangleBase.Height; }
                set { Resize(this.Width, value); }
            }
    
            [Browsable(true), Description("X"), Category("Layout")]
            public int X
            {
                get { return RectangleBase.X; }
                set
                {
                    Point p = new Point(value - RectangleBase.X, RectangleBase.Y);
                    this.Move(p);
                    Canvas.Invalidate();
                }
            }
    
            [Browsable(true), Description("Y"), Category("Layout")]
            public int Y
            {
                get { return RectangleBase.Y; }
                set
                {
                    Point p = new Point(RectangleBase.X, value - RectangleBase.Y);
                    this.Move(p);
                    Canvas.Invalidate();
                }
            }
    
            [Browsable(true), Description("Text"), Category("Layout")]
            public string Text { get;  set; }
    
            public ShapeBase(GraphControl site)
                : base(site)
            {
                Init();
            }
    
            private void Init()
            {
                RectangleBase = new Rectangle(0, 0, 100, 70);
                ShapeBrush = new SolidBrush(Color.SteelBlue);
            }
    
            public override void Paint(Graphics g)
            {
                return;
            }
    
            public override bool Hover(Point p)
            {
                return false;
            }
    
            public override void Invalidate()
            {
                Canvas.Invalidate(RectangleBase);
            }
    
            public override void Move(Point p)
            {
                this.RectangleBase.X += p.X;
                this.RectangleBase.Y += p.Y;
            }
    
            public virtual void Resize(int width, int height)
            {
                this.RectangleBase.Height = height;
                this.RectangleBase.Width = width;
            }
        }
    

    3、新建一个简单的矩形类

        public class LjrRectangle : ShapeBase
        {
            public LjrRectangle(GraphControl s)
                : base(s)
            { }
    
            public override void Paint(Graphics g)
            {
                g.FillRectangle(base.ShapeBrush, base.RectangleBase);
                if (base.IsHover || base.IsSelected)
                {
                    g.DrawRectangle(new Pen(Color.Red, 2F), base.RectangleBase);
                }
                else
                {
                    g.DrawRectangle(base.DefaultPen, base.RectangleBase);
                }
            }
        } 

    4、新建画布GraphControl

    所以自定义图形控件都将在这个画布里绘制、移动等操作

        public class GraphControl : ScrollableControl
        {
            /// <summary>属性控件绑定事件</summary>
            public delegate void ShowProperty(object ent);
    
            /// <summary>属性控件绑定事件</summary>
            public event ShowProperty OnShowProperty;
    
            /// <summary>当前悬停在哪个对象上边</summary>
            protected AbstractShape hoveredObject;
    
            /// <summary>当前选中的对象</summary>
            protected AbstractShape selectedObject;
    
            /// <summary>是否正在拖动</summary>
            protected bool draging = false;
    
            /// <summary>图形对象集合</summary>
            public List<ShapeBase> Shapes { get; set; }
    
            public GraphControl()
            {
                Shapes = new List<ShapeBase>();
            }
    
            protected override void OnPaintBackground(PaintEventArgs e)
            {
                base.OnPaintBackground(e);
    
                Graphics g = e.Graphics;
                Size gridSize = new Size(10, 10);
                ControlPaint.DrawGrid(g, this.ClientRectangle, gridSize, this.BackColor);
            }
    
            protected override void OnPaint(PaintEventArgs e)
            {
                Graphics g = e.Graphics;
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
    
                for (int k = 0; k < Shapes.Count; k++)
                {
                    Shapes[k].Paint(g);
                }
            }
    
            public ShapeBase AddShape(ShapeBase shape)
            {
                Shapes.Add(shape);
                shape.Canvas = this;
                this.Invalidate();
                return shape;
            }
        }
    

    5、新建测试项目

    5.1 新建demo.cs把控件拖入界面左边

    5.2 再拖一个PropertyGrid用来显示属性值

    5.3 Demo.cs代码如下

            private void Demo_Load(object sender, EventArgs e)
            {
                var shape = new LjrRectangle(graphControl1);
                shape.Location = new Point(100, 300);
                shape.Text = "图形化控件";
                this.graphControl1.AddShape(shape);
                this.graphControl1.OnShowProperty += graphControl1_OnShowProps;
            }
    
            private void graphControl1_OnShowProps(object ent)
            {
                this.propertyGrid1.SelectedObject = ent;
            }

    6、运行程序

     

    阅读目录

    • 图形化控件开发 - 矩形控件
    • 图形化控件开发 - 控件移动
    • 图形化控件开发 - 直线连线
    • 图形化控件开发 - 折线连线
    • 图形化控件开发 - 放大缩小
    • 图形化控件开发 - 待定
  • 相关阅读:
    Nginx反向代理和负载均衡
    高并发系统设计的三个目标:性能、可用性和可扩展性
    Spring Cloud alibaba
    分布式集群微服务
    前端那么多好的框架 为什么springboot推荐使用Thymeleaf?
    wpf、winform最大化被任务栏遮挡的解决办法
    SpringCloud Gateway 漏洞分析 (CVE202222947)
    css鼠标移入图片变成发大镜效果
    前端图标库
    前端图标库
  • 原文地址:https://www.cnblogs.com/lanxiaoke/p/7704352.html
Copyright © 2020-2023  润新知