C#使用Stateless和箭头控件实现状态机的控制及显示
之前开发一个小工具,内部实现一个状态机,并显示状态机当前状态及状态间的转移过程。我使用了Stateless开源类库及一个开源自定义箭头控件。自定义箭头控件是HZHControls其中一个控件,我单独把它从源码中独立出来。主要对代码做了以下改动:
- 添加、删除、替换了一部分注释。
- 更改了一些内部事件触发逻辑,时间长了忘了具体改了什么,但不会影响主体功能。
- 在 protected override void OnPaint(PaintEventArgs e) 中内联了外部依赖的 public static void SetGDIHigh(Graphics g) 函数,我在原作者博客的评论下有说明。
以上涉及到的相关项目的链接如下
- Stateless开源类库:https://github.com/dotnet-state-machine/stateless
- HZHControls控件库:https://gitee.com/kwwwvagaa/net_winform_custom_control
- Stateless使用方法:.NET中的状态机库Stateless
- 自定义箭头控件介绍:(六十三)c#Winform自定义控件-箭头(工业)-HZHControls
自定义箭头控件的代码很有学习价值,可以在其基础上扩展出其它形状的控件。使用时新建一个用户控件然后复制代码即可,代码如下:
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
}
}
C#使用Stateless和箭头控件实现状态机的控制及显示的更多相关文章
- [Android Pro] android控件ListView顶部或者底部也显示分割线
reference to : http://blog.csdn.net/lovexieyuan520/article/details/50846569 在默认的Android控件ListView在 ...
- NTKO控件在阅读PDF时,显示DEMO的问题
NTKO控件在阅读PDF时,显示DEMO的问题, 原因是加载了以前的DEMO版本的控件.解决办法是: 在命令行中执行命令: regsvr32 /u NtkoOleDocAll.DLL 卸载老版本的控件 ...
- C# WPF Image控件下对于Base64的转化显示
原文:C# WPF Image控件下对于Base64的转化显示 算作前言 本文对图片如何转化成base64不做描述,我们可以从很多途径了解到转化办法.却很少有博客提到怎么在WPF的Image控件中显示 ...
- kendo UI 倒如css 和 js 后 窗口控件上的工具栏图标不显示如何解决
examples 文档中找到window的例子打开一个 查看其中文件引入 <head> <title>API</title> <meta char ...
- delphi ,1)控件根据窗口大小,一直居中显示 2)显示最大化最小化按钮控件
一.控件根据窗口大小,一直居中显示 1)onResize:当窗体尺寸改变时发生 例子:如何使控件随窗口的放大和缩小动态改变自己的大小,使控件“保存.返回”在窗口变大变小中随着变. 在Panel调用 p ...
- SilverLight:基础控件使用(4)-日期显示和选择类控件
ylbtech-SilverLight-Basic-Control:基础控件使用(4)-日期显示和选择类控件 Calendar,DatePicker 1.A,返回顶部 Calendar控件(日期控件) ...
- 用spin和edit控件来用spin控制edit里面小数的增减
1.响应SPIN的消息,就是点SPIN的上键头和下键头的消息,在这个消息里改变值是以0.1步进量增减.2.使用UpdateData(FALSE)来更新EDIT的关联的double型的变量. 创建步骤 ...
- 【C++自绘控件】如何用GDI+来显示图片
在我们制作一个应用软件的时候往往需要在窗口或控件中添加背景图.而图片不仅有BMP格式的,还有JPEG.PNG.TIFF.GIF等其它的格式.那么如何用jpg格式的图片来当背景呢? 这里用到了GDI+, ...
- repeater控件 + marquee标签 实现文字滚动显示
各种信息网站.BBS等网站上的公告信息模块的实现 拖出一个repeater控件绑定数据库中要显示的信息 在repeater的 <ItemTemplate> ... </ItemTem ...
- vc 在edit控件中动态插入数据滚动显示
内存从网上论坛摘抄整理 思路:给控件设置多行属性,设置垂直滚动条,Auto Vscroll设置为true,放入文本后把插入点设置到末尾 pEdit->LineScroll(pEdit->G ...
随机推荐
- Linux 统计Web服务日志命令
本人在Linux运维中收集的一些通用的统计,Apache/Nginx服务器日志的命令组合. Apache日志统计 # 列出当天访问次数最多的IP命令 [root@lyshark.cnblogs.com ...
- Windows开机自动同步时间
前言 有些Windows客户端因主板电池没电或其他原因,每次启动系统后,读取到BIOS的时间是初始时间(1970年)或错误的时间,这时需要系统启动后立即向时间服务器同步一次时间. 该方法是添加 ...
- uni-app接口请求封装
首先根目录下新建文件夹取名随意,这里我取名common(意为:常见的.共有的) 然后新建request.js文件,贴入以下代码 let server_url = ''; //请求根路径(服务器地址) ...
- easyexcel只通过表名来动态查询并动态导出数据
EasyExcel动态表头即动态数据生成 1️⃣ 业务需求 需要将数据库中的所有表放在一个下拉框中,下拉框支持模糊查询到相关的表,然后通过这个表名查询到数据库的数据,切换不同的表查询出来相关表的列和数 ...
- 12c/19c新特性官方文档快速参考
工作中会经常遇到被询问Oracle某一个新特性,是在哪个版本开始引入,通常都去查官方文档New Features部分章节,下面列出从12.1.0.1 到 19c的对应在线官方文档的链接,方便快速检索: ...
- .NET Core开发实战(第33课:集成事件:使用RabbitMQ来实现EventBus)--学习笔记(上)
33 | 集成事件:使用RabbitMQ来实现EventBus 这一节我们来讲解如何通过 CAP 组件和 RabbitMQ 来实现 EventBus 要实现 EventBus,我们这里借助了 Rabb ...
- Linux-解决jps查看正在运行的Java进程时显示:process information unavailable 问题
背景:jps全称为Java Virtual Machine Process Status Tool,是Java提供的一个查看当前用户有权访问的主机的Java进程情况的工具. 因为每一个Java程序都会 ...
- 使用7-zip进行分卷压缩和解分卷压缩(Windows和Linux)
现在一共有10个视频,一共313M,我对该文件夹进行分卷压缩,每个tar包100M,压缩过程如下: Windows环境首先选中所有的压缩包,然后在压缩包上单击鼠标右键,然后选择7-Zip,再选择提取到 ...
- 山东职业竞赛wp2023(arm、cpython)
pwn2 return2libc,白给 from evilblade import * context(os='linux', arch='amd64') context(os='linux', ar ...
- 【分布式】load balance 02-consistent hash algorithm 一致性哈希算法原理详解
负载均衡系列专题 01-负载均衡基础知识 02-一致性 hash 原理 03-一致性哈希算法 java 实现 04-负载均衡算法 java 实现 概念 一致哈希是一种特殊的哈希算法. 在使用一致哈希算 ...