C# Window form 自定义控件的结构和设计(三)

C# Window form 自定义控件的结构和设计(三)

一、前面介绍了如何来创建第一个自定义的控件,以及一个测试程序。下面我们来看下如何在自定义控件中添加属性。

C#和其他.NET语言支持属性作为语言的第一类成员。把属性作为语言的基础属性有两点主要的有点:

①利用属性使放射返回一个类的属性更加简单。

②编写代码时,我们可以取得或者设置属性,就像取得或者设置一个类的成员变量一样。

接下来,我们来创建一个实现许多属性的自定义控件。

Snipaste_2024-04-14_19-18-13

和之前的程序一样修改基类为System.Windows.Forms.Control。

第一步在类中添加属性值,如下所示:

  public enum TextDirection{VerticalText,HorizonalText};// 字段名称要输出的文本private string displayText;// 文本被输出的次数private int displayCount;// 文本被显示的颜色private Color textColor;// 用来显示文本的字体private Font textFont;// 文本显示方向private TextDirection textDirection;// 文本显示位置private Point startDisplayPoint;// 属性实现public string DisplayText{get { return displayText; }set { displayText = value; Invalidate(); }}public int DisplayCount{get { return displayCount; }set { displayCount = value; Invalidate(); }}public Color TextColor{get { return textColor; }set { textColor = value; Invalidate(); }}public Font TextFont{get { return textFont; }set { textFont = value; Invalidate(); }}public TextDirection TextDirect{get { return textDirection; }set { textDirection = value; Invalidate(); }}public Point StartDisplayPoint{get { return startDisplayPoint; }set { startDisplayPoint = value; Invalidate(); }}

第二步然后添加一个控件Paint事件,代码如下:

 Graphics g = e.Graphics;g.FillRectangle(Brushes.White, ClientRectangle);PointF point = StartDisplayPoint;Brush brush = new SolidBrush(textColor);StringFormat sf = new StringFormat();if (TextFont == null)TextFont = new Font("Times New Roman", 12);if (TextDirect == TextDirection.VerticalText)sf.FormatFlags = StringFormatFlags.DirectionVertical;for (int nCount = 0; nCount < displayCount; nCount++){g.DrawString(displayText, TextFont, brush, point.X, point.Y, sf);if (TextDirect == TextDirection.VerticalText)point.X += TextFont.GetHeight();elsepoint.Y += TextFont.GetHeight();}

运行程序,生成一个CustomControlWithProperties.dll。

接下来我们,我们生成一个测试程序,如下图:

Snipaste_2024-04-14_18-54-53

在窗体编辑器中可以看到我们刚才生成的控件。拖放到窗体中,在右边的控件属性窗口中,我们看到了我们刚才自定义的控件属性值。

二、属性的默认值

在上面自定义控件代码中,所有的属性都是空白的。但是在很多情况下,我们需要把属性值设置为有意义的值。我们需要注意两个问题:

①确定属性是在控件代码中初始化的。

②确定VS编译器了解默认值。

在刚才的程序中,我们添加默认的属性值。代码如下:

 private string displayText = "GoodBye,World";// 文本被输出的次数private int displayCount = 5;// 文本被显示的颜色private Color textColor = Color.Lime;// 用来显示文本的字体private Font textFont = new Font("Times New Roman", 12);// 文本显示方向private TextDirection textDirection = TextDirection.VerticalText;// 文本显示位置private Point startDisplayPoint = new Point(6, 6);

我们需要将默认值显示到VS的属性窗口中,有两种方式:

①在属性的声明前设置一个属性。

在DisplayText,DisplayCount,TextDirect属性中设置如下属性:

// 属性的实现[DefaultValue("Hello,World")]public string DisplayText{get { return displayText; }set { displayText = value; Invalidate(); }}[DefaultValue(3)]public int DisplayCount{get { return displayCount; }set { displayCount = value; Invalidate(); }}[DefaultValue(TextDirection.HorizonalText)]public TextDirection TextDirect{get { return textDirection; }set { textDirection = value; Invalidate(); }}

说明:当我们的属性值属于其值可以作为属性中一个参数的类型(一个字符串,一个数字,或者一个枚举)列出时,这种方式是很好的。

②我们使用一种基于Reset和ShouldSerialize的方法。使用这种方式,我们可以将属性重置为默认值。并将给定属性和默认值比较。更具体的说:Reset负责重置为默认属性。ShouldSerialize检查属性是否具有默认值。

  public void ResetTextColor(){TextColor = Color.Red;}public bool ShouldSerializeTextColor(){return TextColor != Color.Red;}public void ResetTextFont(){TextFont = new Font("Times New Roman",12);}public bool ShouldSerializeTextFont(){return !TextFont.Equals(new Font("Times New Roman", 12));}public void ResetStartDisplayPoint(){StartDisplayPoint = new Point(6,6);}public bool ShouldSerializeStartDisplayPoint(){return StartDisplayPoint != new Point(6, 6);}

运行自定义控件程序,然后再测试程序中再次打开控件属性,可以看到右键菜单项中多了一个重置的功能。

image-20240414195054090
运行自定义控件程序,然后再测试程序中再次打开控件属性,可以看到右键菜单项中多了一个重置的功能。

好了,自定义控件添加属性的功能就介绍到这里了。欢迎大家一起交流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/816007.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flutter第八弹 构建拥有不同项的列表

目标&#xff1a;1&#xff09;项目中&#xff0c;数据源可能涉及不同的模版&#xff0c;显示不同类型的子项&#xff0c;类似RecycleView的itemType, 有多种类型&#xff0c;列表怎么显示&#xff1f; 2&#xff09;不同的数据源构建列表 一、创建不同的数据源 采用类似Rec…

UE C++ 知识杂记

FString、FName与 FText FName&#xff1a;&#xff08;可以有效地存储名称和对资产或对象的引用&#xff09; 它主要用于存储和引用名称&#xff0c;例如对象名称、属性名称和资产名称。引擎中的资源名称都是FName类型&#xff0c;通过一个轻型系统重复使用字符串&#xff0c…

vue3知识点补充第二节

01 自定义Hook 正常的组件&#xff1a;<template><div><img id"img" src"./assets/images/01.png" width"300" height"300"></img></div></template><script>// 导入hook组件 并传递一个…

【设计模式】六大设计原则

设计原则 研究 23 种设计模式是困难的&#xff0c;甚至是没必要的六大设计原则零、单一职责原则开闭原则里氏代换原则依赖倒置原则接口隔离原则迪米特法则合成复用原则 研究 23 种设计模式是困难的&#xff0c;甚至是没必要的 设计模式有23种&#xff0c;我认为对普通人来说想…

快速寻找可以构建出网通信隧道的计算机

点击星标&#xff0c;即时接收最新推文 本文选自《内网安全攻防&#xff1a;红队之路》 扫描二维码五折购书 为加强内网的安全防范&#xff0c;安全管理员往往会限制内网计算机访问互联网&#xff0c;当然不同机构的限制策略是不一样的&#xff0c;有的完全阻断了内网计算机访问…

如何发布自己的Python库?

Python包发布 1、背景概述2、操作指南 1、背景概述 为什么我们要发布自己的Python库&#xff1f;如果你想让你的Python代码&#xff0c;通过pip install xxx的方式供所有人下载&#xff0c;那就需要将代码上传到PyPi上&#xff0c;这样才能让所有人使用 那么&#xff0c;如何发…

Java基础知识总结(54)

&#xff08;1&#xff09; 手动实现LinkedList LinkedList底层结构实现和ArrayList底层数据结构实现有着本质上的区别 ArrayList底层实现主要依赖数组&#xff0c;而LinkedList底层实现则是依赖链表。 /** LinkedList的实现是双向链表&#xff0c;因此需要定义首节点和尾结点…

群晖双硬盘实时备份(WebDAV Server+Cloud Sync)

安装和设置 WebDAV Server WebDAV 是一种基于HTTP的协议扩展&#xff0c;它允许用户在远程Web服务器上进行文档的编辑和管理&#xff0c;就如同这些文件存储在本地计算机上一样。使用WebDAV&#xff0c;用户可以创建、移动、复制和修改文件和文件夹。 安装和设置 Cloud Sync…

2024/4/12 网络编程day2

OSI模型中的网络层次有哪些&#xff1f; 物理层&#xff0c;数据链路层&#xff0c;网络层&#xff0c;传输层&#xff0c;会话层&#xff0c;表示层&#xff0c;应用层TCP/IP协议族的分层有哪些&#xff1f; 网络接口层&#xff0c;网络层&#xff0c;运输层&#xff0c;应用层…

使用 Prometheus 在 KubeSphere 上监控 KubeEdge 边缘节点(Jetson) CPU、GPU 状态

作者&#xff1a;朱亚光&#xff0c;之江实验室工程师&#xff0c;云原生/开源爱好者。 KubeSphere 边缘节点的可观测性 在边缘计算场景下&#xff0c;KubeSphere 基于 KubeEdge 实现应用与工作负载在云端与边缘节点的统一分发与管理&#xff0c;解决在海量边、端设备上完成应…

前端面试问题汇总 - 浏览器篇

1. 本地存储有哪些&#xff0c;区别是什么&#xff1f; Cookies&#xff08;Cookie&#xff09;&#xff1a; 是存储在用户计算机上的小型文本文件&#xff0c;由网站服务器发送到用户的浏览器&#xff0c;然后在用户访问网站时由浏览器发送回服务器。Cookies 可以用来存储用户…

地球上四大洋介绍

地球上四大洋的分布是&#xff1a; 太平洋&#xff1a;太平洋是世界上最大的海洋&#xff0c;覆盖了约三分之一的地球表面。它位于亚洲、澳大利亚、美洲和南极洲之间。太平洋的面积约为1.6亿平方公里&#xff0c;拥有世界上最深的点——马里亚纳海沟。 大西洋&#xff1a;大西…

2024HW --> 安全产品 Powershell无文件落地攻击

在HW中&#xff0c;除了了解中间件&#xff0c;web漏洞&#xff0c;这些攻击的手法&#xff0c;还得了解应急响应&#xff0c;安全产品&#xff0c;入侵排查&#xff0c;溯源反制...... 那么今天&#xff0c;就来说一下安全产品&#xff08;安全公司我就不说了&#xff0c;这个…

ffmpeg cuda硬件解码后处理使用opengl渲染,全硬件流程

1 ffmpeg 硬件解码 使用硬件解码后不要transfer到内存&#xff0c;使用cuda转化nv12 -> bgr24 转化完毕后cuda里面存了一份bgr24 2 gpumat 和 cuda 互操作 如果需要opencv gpumat直接使用cuda内存&#xff0c;则可以手动构造gpumat 可以使用gpumat的各种函数 uchar3* cu…

6-139 大整数存储-数组

本题要求实现一个函数,实现大整数以整数形式存储。大整数按每4位保存在整数数组中,如果大整数位数不是4的倍数,则将保证低位都按4位一存。如“123456789”保存为1,2345,6789。大整数以字符串形式输入 int convert(char a[],int x[]); 函数接口定义: a 是以字符串形式输…

001vscode为什么设置不了中文?

VSCode中文插件安装 在VSCode中设置中文的首要步骤是安装“Chinese (Simplified) Language Pack for Visual Studio Code”扩展插件。这一过程十分简单&#xff0c;只需打开VSCode&#xff0c;进入扩展市场&#xff0c;搜索“ Chinese (Simplified) Language Pack ”然后点击…

【MATLAB源码-第49期】基于蚁群算法(ACO)算法的栅格路径规划,输出最佳路径图和算法收敛曲线图。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 蚁群算法是一种模拟自然界蚂蚁觅食行为的启发式优化算法。在蚁群系统中&#xff0c;通过模拟蚂蚁之间通过信息素沟通的方式来寻找最短路径。 在栅格路径规划中&#xff0c;蚁群算法的基本步骤如下&#xff1a; 1. 初始化: …

MES实施优势有哪些?MES制造执行系统的主要内容

各个行业之间也开始进入到了激烈的竞争当中&#xff0c;很多企业为了能够有效提升企业竞争力&#xff0c;都会通过提升自身实力的方式来提升竞争力。一些制造业也会在经营过程当中使用到MES系统&#xff0c;那么&#xff0c;mes系统的优势有哪些呢&#xff1f; 1、优化企业现场…

mysql dump导出导入数据

前言 mysqldump是MySQL数据库中一个非常有用的命令行工具&#xff0c;用于备份和还原数据库。它可以将整个数据库或者特定的表导出为一个SQL文件&#xff0c;以便在需要时进行恢复或迁移。 使用mysqldump可以执行以下操作&#xff1a; 备份数据库&#xff1a;可以使用mysqld…

ELK日志分析系统+Filebeat

目录 一、Filebeat介绍 1、Filebeat简介 2、Filebeat的工作方式 3、filebeat工作流程 4、Filebeat的作用 5、filebeat的用途 1.为什么要用filebeat来收集日志&#xff1f;为什么不直接用logstash收集日志&#xff1f; 2.filebeat和logstash的区别 二、部署(ELFK)Fileb…