C#自定義控件

1。C#中控件和組件的區別:

一般組件派生于:Component類,所以從此類派生出的稱之為組件。
一般用戶控件派生于:Control類或UserControl類,所以從該類派生出的稱之為用戶控件。
他們之間的關系主要是:UserControl繼承Control繼承Component。

概括:組件包括控件,控件肯定是組件,但組件不一定是控件。

控件的突出特點:就是交互式組件(能動,能和客戶交互),而用戶控件則是將某些特定的組件或控件復合從而實現特定的業務功能。
https://blog.csdn.net/cxu123321/article/details/103014278

2。自定義控件分類?

自定義控件、擴展控件、復合控件
完全自定義控件: 繼承Control類
擴展控件:繼承某個具體的控件類,如:Button,Label等
復合控件:繼承UserControl類,又稱用戶控件UserControl。即:把多個控件通過組合的形式,形成更大,功能更全的控件。

https://www.cnblogs.com/zhangchenliang/archive/2012/08/17/2643744.html
https://blog.csdn.net/yysyangyangyangshan/article/details/7078471

繼承鏈

  • Button具體控件類
    繼承鏈:Button—>ButtonBase—>Control—>Component

  • Control類
    繼承鏈:Control—>Component

  • UserControl類
    繼承鏈:UserControl—>ContainerControl—>ScrollableControl—>Control—>Component
    ContainerControl容器控件,支持其他控件向本控件中拖放。
    ScrollableControl滾動控件,讓控件支持水平和垂直滾動條。

  • Component類

    C# Winform窗體中包括組件和控件兩類:
    組件的基類是Component類
    控件的基類是Control類
    結論:控件肯定是組件,但組件不一定是控件

    控件包含兩種:自定義控件、官方控件
    自定義控件包含三種:
    完全自定義的控件:直接繼承Control類
    擴展控件:直接繼承某一個官方控件,比如:Button,Label等
    用戶控件:最常用一種自定義控件,也是最簡單的,直接繼承UserControl類

用戶控件

概念:

用戶控件:即UserControl,也稱復合控件,又稱組合控件,不能直接運行。必須嵌套在窗體中使用。
用戶控件繼承UserControl類,而UserControl—>…—>繼承Control類

用戶控件怎么創建?怎么設計?怎么使用?

創建:右鍵項目—>用戶控件
在這里插入圖片描述
設計:像窗體一樣去設計。
使用:先編譯,編譯后工具箱發生變化,像使用自帶的控件一樣去使用用戶控件。
建議:用戶控件不建議在使用時編寫業務邏輯,應該把業務邏輯寫到用戶控件中。優缺點:很容易編寫邏輯,但不靈活。把用戶控件的邏輯暴露出去,讓開發者在使用此控件時,定制邏輯。優缺點:邏輯難寫,但靈活。
公開屬性和公共事件把握一個適度原則,切記:不要把用戶控件中的某個具體的官方控件直接公開。

// 一般情況下在用戶控件中最常用公開的:屬性和事件。
public partial class Login : UserControl
{// 公開一個事件,考慮:這個事件什么時候觸發?[Description("登錄事件")]public event EventHandler LoginEvent;public Login(){InitializeComponent();// 用戶控件,開發者不需要重繪,所以一般可以省略這些配置。/*this.SetStyle(ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.DoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint | ControlStyles.SupportsTransparentBackColor, true);*/}private void Login_Load(object sender, EventArgs e){}// 用戶控件:公開屬性//[Category("我的屬性")]//[Category("雜項")]//[Category()][Category][DefaultValue(typeof(string), "賬號:")]  // DefaultValue//[Obsolete]// 以上的特性都可以不用,如下的特性在自定義控件時,常用[Description("賬號的標題,默認值賬號:")]  // 主要提示用的[Browsable(true)]  // 控制某個公開屬性是否可以在屬性窗口中被開發者看見。使用時只能通過代碼訪問。public string AccountText{get { return this.lblAccount.Text; }set{if (string.IsNullOrWhiteSpace(value))throw new ArgumentNullException("AccountText屬性不能為空!");if (value.Length != 3)throw new ArgumentNullException("AccountText屬性只能輸入3個漢字或字母!");this.lblAccount.Text = value;}}[Description("賬號")]public string Account{get { return this.txtAccount.Text; }set{this.txtAccount.Text = value;}}[Description("密碼")]public string Password{get { return this.txtPassword.Text; }set{this.txtPassword.Text = value;}}// LoginEvent的觸發時機:讓用戶點擊btnLogin按鈕時,觸發LoginEvent事件。private void btnLogin_Click(object sender, EventArgs e){//if (LoginEvent != null)//    LoginEvent.Invoke(sender, e);// 簡寫LoginEvent?.Invoke(sender, e);}
}

擴展控件

擴展控件怎么創建?怎么設計?怎么使用?

創建:兩種方法,通過用戶控件和組件修改而來。
設計:不建議使用設計器,建議直接編寫代碼。(難點)
使用:先編譯,編譯后工具箱發生變化,像使用自帶的控件一樣去使用擴展控件。
設計步驟:
a. 先公開擴展屬性,事件等
b.在擴展控件類中,使用相應的屬性實現具體的業務邏輯流。(重點:重寫OnPaint事件!)

// 把一個用戶控件改寫成擴展控件,只需要把UserControl基類,改寫成具體的控件類即可!
// 通過用戶控件改寫后,把錯誤修復一下即可。
// InitializeComponent()中的this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;去掉即可!

 public partial class MyTextBox : TextBox{public MyTextBox(){InitializeComponent();}[Description("文本框的背景,使用方式同BackColor")]public Color MyBackColor{get{return this.BackColor;}set{this.BackColor = value;Refresh();}}}

3。特性簡單理解?

CategoryAttribute DescriptionAttribute
特性(Attribute)是用于在運行時傳遞程序中各種元素(比如類、屬性、方法、結構、枚舉、組件等)的行為信息的聲明性標簽。您可以通過使用特性向程序添加聲明性信息。一個聲明性標簽是通過放置在它所應用的元素前面的方括號([ ])來描述的。

特性是運行時給各種元素添加聲明性標簽。語法:[某個特性]

特性(Attribute)用于添加元數據,如編譯器指令和注釋、描述、方法、類等其他信息。.Net 框架提供了兩種類型的特性:預定義特性和自定義特性。
https://www.toutiao.com/article/6969542149637833230
https://www.toutiao.com/article/7106017793186824744

完全自定義控件

完全自定義控件繼承Control,不是繼承UserControl,VS2022中沒有提供定義完全自定義控件的模板。
1.方法1:通過用戶控件,改寫成完全自定義控件。
2.方法2:通過組件,改寫成完全自定義控件。

通過用戶控件改寫后,把錯誤修復一下即可。
InitializeComponent()中的this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;去掉即可!

    public partial class MyLabel : Control{// 私有字段,畫圖時使用private Font font = new Font("宋體", 9, FontStyle.Regular, GraphicsUnit.Point);public MyLabel(){InitializeComponent();// ControlStyles枚舉項逐個設置,解決重繪時閃爍的問題/* this.SetStyle(ControlStyles.UserPaint, true);//自繪this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); //雙緩沖,為了兼容this.SetStyle(ControlStyles.DoubleBuffer, true);// 雙緩沖,主要解決閃爍的問題this.SetStyle(ControlStyles.ResizeRedraw, true); //調整大小時重繪this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); //禁止檫除背景this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); //透明效果*/// 簡寫:把ControlStyles多個枚舉項都設置成truethis.SetStyle(ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.DoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint | ControlStyles.SupportsTransparentBackColor, true);this.BackColor = ColorTranslator.FromHtml("#ECE9D8");this.MouseEnter += MyLabel_MouseEnter;this.MouseLeave += MyLabel_MouseLeave;}private void MyLabel_MouseLeave(object sender, EventArgs e){this.TextColor = Color.FromArgb(22, 95, 162);this.Cursor = Cursors.Arrow;font = new Font("宋體", 9, FontStyle.Regular, GraphicsUnit.Point);Refresh();}private void MyLabel_MouseEnter(object sender, EventArgs e){this.TextColor = Color.Red;this.Cursor = Cursors.Hand;font = new Font("宋體", 12, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point);Refresh();}/// <summary>/// 對畫布配置,讓畫面畫出來的圖形更清晰,質量更高/// </summary>/// <param name="g">畫布</param>private void SetGraphics(Graphics g){// 設置合成模式為源覆蓋g.CompositingMode = CompositingMode.SourceOver;// 合成圖像時,使用高質量模式g.CompositingQuality = CompositingQuality.HighQuality;// 抗鋸齒(讓畫筆,畫刷平滑些,更清晰)g.SmoothingMode = SmoothingMode.AntiAlias;// 設置插值模式為高質量雙三次插值g.InterpolationMode = InterpolationMode.HighQualityBicubic;}// 完全自定義的控件要求:// 1。必須繼承Control類。// 2。需要重繪(你自己畫控件),需要重寫一個方法OnPaint()// 3。考慮閃屏(雙緩沖),固定配置protected override void OnPaint(PaintEventArgs e){base.OnPaint(e); // 調用基類OnPaint,可以省略。也可以留下。留下時建議寫到第一行。// 如何畫圖?使用GDI或GDI+技術。后面會講,今天了解一下。// 畫板,畫筆,畫刷,畫開狀,畫筆或畫刷的顏色,粗細Graphics g = e.Graphics;// 畫布SetGraphics(g);// 對畫布做一些設置SolidBrush brush = new SolidBrush(TextColor);// 畫刷RectangleF rectF = new RectangleF(5, 5, this.Width - 10, this.Height - 10);g.FillRectangle(new SolidBrush(Color.Gray), rectF);  // 把矩形填充顏色g.DrawString(MyText, font, brush, rectF, Format);}// 公開的3個屬性TextColor、MyText、Format(只讀)private Color textColor = Color.FromArgb(22, 95, 162);[Description("文本顏色")]public Color TextColor{get { return textColor; }set{textColor = value;Refresh();//Update();//Invalidate();}}[Description("文本內容")]public string MyText{get{return this.Text;}set{this.Text = value;Refresh();}}private StringFormat format = null;[Description("設置文本對齊格式")]public StringFormat Format{get{if (format == null){format = new StringFormat();format.Alignment = StringAlignment.Center;  // 水平居中format.LineAlignment = StringAlignment.Center;  // 垂直居中format.FormatFlags = StringFormatFlags.NoWrap;  // 不換行format.Trimming = StringTrimming.EllipsisCharacter; // 超出加省略號}return format;}}}
  • 屬性顯示在雜項中如下圖
    在這里插入圖片描述

自定義組件

 // 組件:一般情況組件不帶界面效果,只帶業務邏輯// 自己封裝了一個定時器組件。public partial class MyTimer : Component{//System.Windows.Forms.Timer工具箱中的定時器//System.Timers.Timer//System.Threading.Timerprivate Timer _timer = new Timer();public event EventHandler TimerTick;// 無參構造函數,給代碼public MyTimer(){InitializeComponent();// 實例化一個定時器_timer = new Timer(TimerInterval);// Elapsed事件相當于System.Windows.Forms.Timer定時器中的Tick事件_timer.Elapsed += _timer_Elapsed;}private void _timer_Elapsed(object sender, ElapsedEventArgs e){TimerTick?.Invoke(sender, e);}// 有參構造函數,給設計器用的public MyTimer(IContainer container){// 把當前的組件this添加容器container中container.Add(this);InitializeComponent();// 實例化一個定時器_timer = new Timer(TimerInterval);// Elapsed事件相當于System.Windows.Forms.Timer定時器中的Tick事件_timer.Elapsed += _timer_Elapsed;}[Description("定時器間隔時間,單位毫秒,默認值1000")]public double TimerInterval{get { return _timer.Interval; }set { _timer.Interval = value; }}[Description("是否啟用定時器")]public bool TimerEnabled{get{return _timer.Enabled;}set{_timer.Enabled = value;}}}

4。反射?

反射是指在程序運行中,查看、操作其他程序集或者自身的元數據的各種信息(類、方法,屬性、變量、對象等)的行為。C#中的反射(Reflection)是一種強大的特性,允許你在運行時檢查和操作程序集、類型和對象的信息,基本上,使用反射可以在代碼運行時檢查和操作指定的類及其成員。C#反射的原理主要基于元數據(與C#特性相似),即程序集中存儲的有關類型、方法等的信息。因為反射可以在程序編譯后獲得信息,所以它提高了程序的拓展性和靈活性。

  // 反射最大的目的為了解耦。// 加載Model.dll程序集,只有加載了程序集,才能創建程序集中某個類的實例。Assembly assembly = Assembly.Load("Model");// 拿Model.Student的實例,相當于 Student s = new Student();object stu = assembly.CreateInstance("Model.Student");// 拿到Model.Student的實例的類型,類型Model.StudentType type = stu.GetType();// 拿到實例的Name屬性PropertyInfo name = type.GetProperty("Name");// 設置Name屬性的值為張三,相當于s.Name = "張三";name.SetValue(stu, "張三");// 拿到Name屬性的值,輸出張三Console.WriteLine(name.GetValue(stu));  MethodInfo method = type.GetMethod("ToString");Console.WriteLine(method.Invoke(stu, null));// 獲取所有的方法和屬性MethodInfo[] methodInfos = type.GetMethods();PropertyInfo[] propertyInfos = type.GetProperties();

反射就是為了拿到各種元素對應的標簽。Reflection反射
https://blog.csdn.net/qq_57671924/article/details/134208556
https://blog.csdn.net/naer_chongya/article/details/130532672

5。練習題:
a.圓角按鈕:(自定義控件應用)
https://blog.csdn.net/shi_xi_sheng/article/details/130969580

b.單行文本框定高、文本垂直居中問題:(自定義控件應用)
https://www.cnblogs.com/weekend001/p/3518020.html
https://blog.csdn.net/mazhiyuan1981/article/details/124350065
https://blog.csdn.net/ngl272/article/details/125226552

c.winform界面美化技巧:IrisSkin4皮膚
https://blog.csdn.net/weixin_37864926/article/details/131822828

d.winform UI庫:
https://www.cnblogs.com/bfyx/p/11361809.html
https://www.cnblogs.com/dxqNet/p/17088088.html
https://www.zhihu.com/question/267772520/answers/updated

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/89039.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/89039.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/89039.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

網絡資產測繪工具全景解析:七大平臺深度洞察

?一、資產測繪工具的核心價值?網絡資產測繪&#xff08;Cyber Asset Intelligence&#xff09;技術通過主動掃描與被動分析&#xff1a;實時發現全球暴露的網絡設備&#xff08;服務器、攝像頭、IoT設備&#xff09;自動化構建資產指紋庫&#xff08;操作系統/服務/框架版本&…

編程語言設計目的與側重點全解析(主流語言深度總結)

編程語言的設計本質上是對計算邏輯的形式化表達與工程約束的平衡&#xff0c;不同語言因目標場景、時代需求和技術哲學的差異&#xff0c;形成了獨特的設計范式。以下從系統級、應用級、腳本/動態、函數式、并發/安全等維度&#xff0c;選取10種最具代表性的編程語言&#xff0…

重學前端003 --- 響應式網頁設計 CSS 顏色

文章目錄文檔聲明head顏色模型div根據在這里 Freecodecamp 實踐&#xff0c;記錄筆記總結。 文檔聲明 在文檔頂部添加 DOCTYPE html 聲明 <!DOCTYPE html>head title 元素為搜索引擎提供了有關頁面的額外信息。 它還通過以下兩種方式顯示 title 元素的內容&#xff1a…

這個Pandas函數可以自動爬取Web圖表

Pandas作為數據科學領域鰲頭獨占的利器&#xff0c;有著豐富多樣的函數&#xff0c;能實現各種意想不到的功能。 作為學習者沒辦法一次性掌握Pandas所有的方法&#xff0c;需要慢慢積累&#xff0c;多看多練。 這次為大家介紹一個非常實用且神奇的函數-read_html()&#xff0…

vLLM與SGLang在自然語言處理領域的技術架構與性能對比研究

隨著大語言模型在工業界和學術界的廣泛應用&#xff0c;高效推理框架的選擇成為自然語言處理領域的關鍵挑戰。vLLM與SGLang作為當前最前沿的推理優化框架&#xff0c;分別通過創新的PagedAttention和RadixAttention機制展現了獨特的技術優勢。本文將系統對比兩大框架的核心架構…

樓宇自動化:Modbus 在暖通空調(HVAC)中的節能控制(二)

Modbus 在 HVAC 節能控制中的應用案例案例一&#xff1a;某商業建筑 HVAC 系統節能改造某大型商業建筑&#xff0c;總建筑面積達 5 萬平方米&#xff0c;涵蓋了購物中心、餐飲區和娛樂場所等多種功能區域 。改造前&#xff0c;其 HVAC 系統采用傳統的控制方式&#xff0c;設備之…

win10安裝Elasticsearch

1 啟動elasticsearch 下載地址&#xff1a;Download Elasticsearch | Elastic 雙擊elasticsearch.bat elasticsearch黑窗口啟動亂碼問題解決方案 到 config 文件下找到 jvm.options 文件 打開后 在文件末尾空白處 添加 -Dfile.encodingGBK 保存后重啟即可。 啟動后輸入&am…

[Meetily后端框架] Whisper轉錄服務器 | 后端服務管理腳本

第七章&#xff1a;Whisper轉錄服務器 歡迎回來&#xff01; 到目前為止&#xff0c;我們已經深入探索了"meeting-minutes"項目的"大腦"——Python后端。 我們已經了解了它如何通過后端API網關接收文本轉錄&#xff0c;使用摘要數據結構&#xff08;Pyd…

Azure-ADF 抽取數據

1,Azure 訪問地址 1,國際版 https://portal.azure.com/#homehttps://portal.azure.com/#home2,世紀互聯中國版 Microsoft Azure 由世紀互聯運營https://portal.azure.cn/2,創建資源組并且所有的后續組件都是再此資源下面創建。 3,創建Data Factory 工具 4,核心組件 1. 管…

django queryset 去重

在Django中&#xff0c;使用QuerySet時&#xff0c;如果你想要對查詢結果進行去重&#xff08;即去除重復的記錄&#xff09;&#xff0c;你可以使用幾種不同的方法。這里列出了一些常見的方法&#xff1a; 使用distinct() distinct()方法用于返回QuerySet中不重復的唯一對象。…

WIFI MTU含義 ,協商修改的過程案例分析

WIFI MTU含義 ,協商修改的過程案例分析 文章目錄 **WIFI MTU含義 ,協商修改的過程案例分析****一、WIFI MTU的含義****二、MTU協商修改的過程案例分析****1. TCP/IP協議中的MTU協商****2. 藍牙(BLE)中的MTU協商****3. 網絡設備配置中的MTU調整****三、協商修改的注意事項**…

記一次Android Studio編譯報錯:Execution failed for task ‘:app:compileDebugAidl‘

問題背景: android studio導入AIDL文件的時候編譯提示: Execution failed for task :app:compileDebugAidl. > A failure occurred while executing com.android.build.gradle.tasks.AidlCompile$AidlCompileRunnable > com.android.ide.common.process.ProcessEx…

selenium跳轉到新頁面時如何進行定位

在 Selenium 中&#xff0c;當你跳轉到新頁面&#xff08;例如通過點擊鏈接、提交表單或 JavaScript 重定向&#xff09;時&#xff0c;通常會遇到頁面加載或窗口切換的問題。為了在新頁面上繼續進行頁面定位操作&#xff0c;你需要確保以下幾點&#xff1a;? 1. 等待頁面加載…

QT——QComboBox組合框控件

QComboBox概述QComboBox是Qt框架中提供的組合框控件&#xff0c;它結合了按鈕和下拉列表的功能&#xff0c;允許用戶從預定義的選項列表中選擇一個或多個項目。基本特性特性描述顯示方式顯示當前選中項&#xff0c;點擊后展開下拉列表編輯能力可設置為可編輯或不可編輯項目類型…

CentOS 安裝jenkins筆記

1. 安裝 Java。目前一般jdk要求11以上&#xff0c;否則會報錯2. 手動添加 Jenkins 倉庫先創建一個專門的Jenkins文件夾&#xff1a;mkdir jenkins然后 執行 sudo curl -fsSL https://pkg.jenkins.io/redhat/jenkins.io.key -o /etc/pki/rpm-gpg/jenkins.io.key 然后&#xff0…

C#枚舉:從基礎到高級的全方位解析

C#枚舉&#xff1a;從基礎到高級的全方位解析 在 C# 編程中&#xff0c;枚舉&#xff08;Enum&#xff09;是一種特殊的值類型&#xff0c;用于定義命名的常量集合&#xff0c;它為代碼提供了更強的類型安全、可讀性和可維護性。從簡單的狀態標識到復雜的位運算組合&#xff0c…

[spring6: Resource ResourceLoader ResourceEditor]-加載資源

Resource Resource 接口為處理和訪問不同類型資源&#xff08;如文件、URL、輸入流等&#xff09;提供了統一的 API&#xff0c;支持資源的存在性檢查、讀取、轉換等操作。 public interface Resource extends InputStreamSource {boolean exists();default boolean isReadable…

Spring Boot - Spring Boot 集成 MyBatis 分頁實現 PageHelper

一、PageHelper 概述 PageHelper 是一個優秀的 MyBatis 分頁插件&#xff0c;可以方便地在 Spring Boot 項目中使用 MyBatis 結合 PageHelper 實現分頁功能二、PageHelper 引入 1、依賴引入 pom.xml <properties>...<postgresql.verison>42.5.6</postgresql.ver…

jenkins自動化部署前端vue+docker項目

文章目錄一、準備工作二、編寫dockerfile文件三、新建jenkins任務一、準備工作 默認你的服務器centos已經搭建完成&#xff0c;同時已經安裝了jenkins和docker。 接下來去下載開源項目ruoyi并上傳到自己的gitee中。 二、編寫dockerfile文件 打開項目工程&#xff0c;在rouy…

opencv中contours的使用

一 Contour FindingContours使用 STL-style vector<> 表示&#xff0c;如 vector<cv::Point>, vector<cv::Point2f>。opencv中&#xff0c;使用函數 cv::findContours() 尋找contours&#xff0c; 具體函數定義如下&#xff1a;void cv::findContours(cv::In…