• C#使用Stateless和箭头控件实现状态机的控制及显示


    之前开发一个小工具,内部实现一个状态机,并显示状态机当前状态及状态间的转移过程。我使用了Stateless开源类库及一个开源自定义箭头控件。自定义箭头控件是HZHControls其中一个控件,我单独把它从源码中独立出来。主要对代码做了以下改动:

    • 添加、删除、替换了一部分注释。
    • 更改了一些内部事件触发逻辑,时间长了忘了具体改了什么,但不会影响主体功能。
    • protected override void OnPaint(PaintEventArgs e) 中内联了外部依赖的 public static void SetGDIHigh(Graphics g) 函数,我在原作者博客的评论下有说明。

    以上涉及到的相关项目的链接如下

    自定义箭头控件的代码很有学习价值,可以在其基础上扩展出其它形状的控件。使用时新建一个用户控件然后复制代码即可,代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.ComponentModel;
    
    namespace ExtControls
    {    
        public partial class  Arrow : UserControl
        {
            private Color arrowColor = Color.DarkGray;
            /// <summary>
            /// 获取设置箭头颜色
            /// </summary>
            [Description("箭头颜色"), Category("自定义")]
            public Color ArrowColor
            {
                get { return arrowColor; }
                set
                {
                    arrowColor = value;
                    Refresh();
                }
            }
            
            private Color? borderColor = null;
            /// <summary>
            /// 获取或设置箭头边框颜色
            /// </summary>
            [Description("箭头边框颜色,为空则无边框"), Category("自定义")]
            public Color? BorderColor
            {
                get { return borderColor; }
                set
                {
                    borderColor = value;
                    Refresh();
                }
            }
            
            /// <summary>
            /// 箭头方向
            /// </summary>
            private ArrowDirection direction = ArrowDirection.Right;
    
            /// <summary>
            /// 获取或设置箭头方向
            /// </summary>
            /// <value>The direction.</value>
            [Description("获取或设置箭头方向"), Category("自定义")]
            public ArrowDirection Direction
            {
                get { return direction; }
                set
                {
                    direction = value;
                    ResetMyPath();
                    Refresh();
                }
            }
    
            private string text;
            /// <summary>
            /// 与控件关联的文本。
            /// </summary>
            [Bindable(true)]
            [Browsable(true)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
            [EditorBrowsable(EditorBrowsableState.Always)]
            [Localizable(true)]
            [Description("与控件关联的文本"), Category("自定义")]
            public override string Text
            {
                get
                {
                    return text;
                }
                set
                {
                    text = value;
                    Refresh();
                }
            }
            /// <summary>
            /// 图形空间
            /// </summary>
            GraphicsPath myPath;
            /// <summary>
            /// 初始化UCArrow类的新实例。
            /// </summary>
            public Arrow()
            {
                this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
                this.SetStyle(ControlStyles.DoubleBuffer, true);
                this.SetStyle(ControlStyles.ResizeRedraw, true);
                this.SetStyle(ControlStyles.Selectable, true);
                this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
                this.SetStyle(ControlStyles.UserPaint, true);
                this.ForeColor = Color.White;
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
                this.SizeChanged += UCArrow_NeedResetChanged;
                this.Size = new Size(100, 50);
                this.ForeColorChanged += UCArrow_NeedResetChanged;
                this.ForeColor = Color.Black;
                this.FontChanged += UCArrow_NeedResetChanged;
            }
    
            /// <summary>
            /// 需要重绘控件的事件
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            void UCArrow_NeedResetChanged(object sender, EventArgs e)
            {
                ResetMyPath();
            }
    
            /// <summary>
            /// 重置图形
            /// </summary>
            private void ResetMyPath()
            {
                Point[] ps = null;
                switch (direction)
                {
                    case ArrowDirection.Left:
                        ps = new Point[] 
                        { 
                            new Point(0,this.Height/2),
                            new Point(40,0),
                            new Point(40,this.Height/4),
                            new Point(this.Width-1,this.Height/4),
                            new Point(this.Width-1,this.Height-this.Height/4),
                            new Point(40,this.Height-this.Height/4),
                            new Point(40,this.Height),
                            new Point(0,this.Height/2)
                        };
                        break;
                    case ArrowDirection.Right:
                        ps = new Point[] 
                        {
                            new Point(0,this.Height/4),
                            new Point(this.Width-40,this.Height/4),
                            new Point(this.Width-40,0),
                            new Point(this.Width-1,this.Height/2),
                            new Point(this.Width-40,this.Height),
                            new Point(this.Width-40,this.Height-this.Height/4),                      
                            new Point(0,this.Height-this.Height/4),
                            new Point(0,this.Height/4)
                        };
                        break;
                    case ArrowDirection.Top:
                        ps = new Point[] 
                        {
                           new Point(this.Width/2,0),
                           new Point(this.Width,40),
                           new Point(this.Width-this.Width/4,40),
                           new Point(this.Width-this.Width/4,this.Height-1),
                           new Point(this.Width/4,this.Height-1),
                           new Point(this.Width/4,40),
                           new Point(0,40),
                           new Point(this.Width/2,0),
                        };
                        break;
                    case ArrowDirection.Bottom:
                        ps = new Point[] 
                        {
                           new Point(this.Width-this.Width/4,0),
                           new Point(this.Width-this.Width/4,this.Height-40),
                           new Point(this.Width,this.Height-40),
                           new Point(this.Width/2,this.Height-1),
                           new Point(0,this.Height-40),
                           new Point(this.Width/4,this.Height-40),
                           new Point(this.Width/4,0),
                           new Point(this.Width-this.Width/4,0),                      
                        };
                        break;
                    case ArrowDirection.Left_Right:
                        ps = new Point[] 
                        { 
                            new Point(0,this.Height/2),
                            new Point(40,0),
                            new Point(40,this.Height/4),
                            new Point(this.Width-40,this.Height/4),
                            new Point(this.Width-40,0),
                            new Point(this.Width-1,this.Height/2),
                            new Point(this.Width-40,this.Height),
                            new Point(this.Width-40,this.Height-this.Height/4),
                            new Point(40,this.Height-this.Height/4),
                            new Point(40,this.Height),
                            new Point(0,this.Height/2),                       
                        };
                        break;
                    case ArrowDirection.Top_Bottom:
                        ps = new Point[] 
                        {
                           new Point(this.Width/2,0),
                           new Point(this.Width,40),
                           new Point(this.Width-this.Width/4,40),
                           new Point(this.Width-this.Width/4,this.Height-40),
                           new Point(this.Width,this.Height-40),
                           new Point(this.Width/2,this.Height-1),
                           new Point(0,this.Height-40),
                           new Point(this.Width/4,this.Height-40),
                           new Point(this.Width/4,40),
                           new Point(0,40),
                           new Point(this.Width/2,0),                      
                        };
                        break;
                }
                myPath = new GraphicsPath();
                myPath.AddLines(ps);
                myPath.CloseAllFigures();
            }
    
            /// <summary>
            /// 引发Control.Paint 事件。
            /// </summary>
            /// <param name="e"></param>
            protected override void OnPaint(PaintEventArgs e)
            {
                base.OnPaint(e);
                var g = e.Graphics;
    
                // 设置GDI高质量模式抗锯齿
                g.SmoothingMode = SmoothingMode.AntiAlias;
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.CompositingQuality = CompositingQuality.HighQuality;
    
                g.FillPath(new SolidBrush(arrowColor), myPath);
    
                if (borderColor != null && borderColor != Color.Empty)
                    g.DrawPath(new Pen(new SolidBrush(borderColor.Value)), myPath);
                if (!string.IsNullOrEmpty(text))
                {
                    var size = g.MeasureString(Text, Font);
                    g.DrawString(Text, Font, new SolidBrush(ForeColor), new PointF((this.Width - size.Width) / 2, (this.Height - size.Height) / 2));
                }
            }
    
            
        }
    
        /// <summary>
        /// 箭头方向的描述枚举
        /// </summary>
        public enum ArrowDirection
        {
            /// <summary>
            /// 向左
            /// </summary>
            Left,
            /// <summary>
            /// 向右
            /// </summary>
            Right,
            /// <summary>
            /// 向上
            /// </summary>
            Top,
            /// <summary>
            /// 向下
            /// </summary>
            Bottom,
            /// <summary>
            /// 向左向右
            /// </summary>
            Left_Right,
            /// <summary>
            /// 向上向下
            /// </summary>
            Top_Bottom
        }
    }
    
  • 相关阅读:
    Run Book Automation
    Android.mk中的经常使用语法
    层的匀速运动波动处理
    【ArcGIS 10.2新特性】ArcGIS 10.2 for Server常见问题
    WPF-19:分享一个样式(左右滑动选中的checbox)
    [置顶] 程序员期望月薪那些事儿
    【VB/.NET】Converting VB6 to VB.NET 【Part II】【之四】
    两种方式给列表增加自动增长序号列
    在后台运行erlang;在需要时连回交互模式
    php设计模式——UML类图
  • 原文地址:https://www.cnblogs.com/timefiles/p/CsharpStatelessArrowStateMachine.html
Copyright © 2020-2023  润新知