圖形化控件開發 - 矩形控件

最近這段時間,公司須要作一個圖形化配置工具。html

主要是有如下一些要求:框架

一、針對一些底層的智能設備(智能樓宇的控制器),經過COM口鏈接上,並經過相關協議讀取參數值ide

二、支持一些基本的邏輯運算,以及公司業務的一些特性「點」,一種點能夠當作一個圖形化控件工具

三、參數在圖形化工具上顯示出來,工程人員直接設置圖形屬性設置參數值、連線等測試

四、支持在線和離線2種工做方式,設置好參數後直接在界面上下載到設備裏字體

五、工做太支持拖動,連線,放大縮小,保存設計文件等this

六、「點」的自己業務要求,略。。。設計

 

通過一番調研,winfrom的圖形化控件技術,並無成熟的框架出來。htm

只有一些零碎的demo,大致上的思路是經過重繪來實現具體的圖形控件。對象

在這裏也提一下Netron框架,這個框架代碼我看了不少遍,不少思路都從這裏來,可是太繁瑣了,改動起來很是吃力

因此我本身從新寫了一遍,大致思路沒變,只是走精簡路線,如下是咱們的工具最終的界面樣式,

我打算把每一步都分拆貼出來,作成一個教程。給你們一個參考

 

 

一、新建自定義控件抽象類

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);
    }

二、繪製一個自定義控件基類

包含一些基本屬性及一些共性方法實現

    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;
        }
    }

三、新建一個簡單的矩形類

    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);
            }
        }
    } 

四、新建畫布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.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;
        }

六、運行程序

 

 

閱讀目錄

  • 圖形化控件開發 - 矩形控件
  • 圖形化控件開發 - 控件移動
  • 圖形化控件開發 - 直線連線
  • 圖形化控件開發 - 折線連線
  • 圖形化控件開發 - 放大縮小
  • 圖形化控件開發 - 待定
相關文章
相關標籤/搜索