WinForm Custom(一) Button控制項

来源:https://www.cnblogs.com/zhuanghamiao/archive/2022/06/07/winform-custom-button.html
-Advertisement-
Play Games

以下代碼實現自定義Button,繼承WinForm的Button,新增了邊框、圓角設置的相關屬性。 public class ZhmButton : Button { private int borderSize = 0; // 邊框 private Color borderColor = Colo ...



以下代碼實現自定義Button,繼承WinForm的Button,新增了邊框、圓角設置的相關屬性。

    public class ZhmButton : Button
    {
        private int borderSize = 0; // 邊框
        private Color borderColor = ColorTranslator.FromHtml("#5A6268"); // 邊框色
        private int borderRadius = 25; //圓角角度

        public ZhmButton()
        {
            // 去除系統預設樣式,並設置自定義樣式
            this.FlatStyle = FlatStyle.Flat;
            this.FlatAppearance.BorderSize = 0;

            this.Size = new Size(150, 46);
            this.BackColor = ColorTranslator.FromHtml("#23272B");
            this.ForeColor = Color.White;
            this.Resize += ZhmButton_Resize;
        }

        [Category("擴展屬性")]
        public int BorderSize { get => borderSize; set { borderSize = value; this.Invalidate(); } }
        [Category("擴展屬性")]
        public Color BorderColor { get => borderColor; set { borderColor = value; this.Invalidate(); } }
        [Category("擴展屬性")]
        public int BorderRadius
        {
            get => borderRadius; set
            {
                borderRadius = value <= Height ? value : Height;
                this.Invalidate();
            }
        }


        private GraphicsPath DrawGraphicsPath(RectangleF rectangle, float radius)
        {
            GraphicsPath path = new GraphicsPath();
            path.StartFigure();

            // 從左上角開始按順時針方向 分別在空間的四個角追加一段圓弧
            //       270°
            //        |
            //180°----|-----0°
            //        |
            //       90°
            path.AddArc(rectangle.X, rectangle.Y, radius, radius, 180, 90);
            path.AddArc(rectangle.Width - radius, rectangle.Y, radius, radius, 270, 90);
            path.AddArc(rectangle.Width - radius, rectangle.Height - radius, radius, radius, 0, 90);
            path.AddArc(rectangle.X, rectangle.Height - radius, radius, radius, 90, 90);

            path.CloseFigure();
            return path;
        }

        private void ZhmButton_Resize(object sender, EventArgs e)
        {
            if (borderRadius > this.Height)
                borderRadius = this.Height;
        }

        protected override void OnPaint(PaintEventArgs pevent)
        {
            base.OnPaint(pevent);

            pevent.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            RectangleF rectSurface = new RectangleF(0, 0, this.Width, this.Height);
            RectangleF rectBorder = new RectangleF(1, 1, this.Width - 0.8F, this.Height - 1);
            if (BorderRadius > 2)
            {
                using (var pathSurface = DrawGraphicsPath(rectSurface, BorderRadius))
                using (var pathBorder = DrawGraphicsPath(rectBorder, BorderRadius - 1))
                using (var penSurface = new Pen(this.Parent.BackColor, 2))
                using (var penBorder = new Pen(BorderColor, BorderSize))
                {
                    penBorder.Alignment = PenAlignment.Inset;
                    this.Region = new Region(pathSurface);
                    pevent.Graphics.DrawPath(penSurface, pathSurface);
                    if (BorderSize > 0)
                        pevent.Graphics.DrawPath(penBorder, pathBorder);
                }
            }
            else
            {
                this.Region = new Region(rectSurface);
                if (BorderSize > 0)
                {
                    using (var penBorder = new Pen(BorderColor, BorderSize))
                    {
                        penBorder.Alignment = PenAlignment.Inset;
                        pevent.Graphics.DrawRectangle(penBorder, 0, 0, this.Width - 1, this.Height - 1);
                    }
                }
            }
        }

        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
            this.Parent.BackColorChanged += Parent_BackColorChanged;
        }

        private void Parent_BackColorChanged(object sender, EventArgs e)
        {
            if(this.DesignMode)
                this.Invalidate();
        }
    }

--------------------------------------------------------以下僅為湊字數---------------------------------------------------------------------------------
使用 .NET Framework 可以開發和實現新的控制項。 可以通過繼承來擴展熟悉的用戶控制項和現有控制項的功能。 還可以編寫自定義控制項,這些控制項執行自己的繪製。
基控制項類
Control 類是 Windows 窗體控制項的基類。 它提供了在 Windows 窗體應用程式中進行可視顯示所需的基礎結構。
Control 類執行下列任務,以便在 Windows 窗體應用程式中提供可視顯示:
公開視窗句柄。
管理消息路由。
提供滑鼠和鍵盤事件,以及許多其他用戶界面事件。
提供高級佈局功能。
包含特定於可視化顯示的多個屬性,如 ForeColor、BackColor、Height 和 Width。
為 Windows 窗體控制項充當 Microsoft® ActiveX® 控制項提供必需的安全性和線程支持。
由於基類提供了大量基礎結構,因此使開發自己的 Windows 窗體控制項變得相對簡單。

控制項種類
Windows 窗體支持三種用戶定義的控制項:複合、擴展和自定義。 以下各節分別介紹各種控制項,並就如何選擇項目中使用的控制項種類提供建議。

複合控制項
複合控制項是封裝在公共容器內的 Windows 窗體控制項的集合。 這種控制項有時稱為用戶控制項。 其包含的控制項稱為構成控制項。
複合控制項包含與每個包含的 Windows 窗體控制項相關聯的所有固有功能,允許選擇性地公開和綁定它們的屬性。 複合控制項還提供了大量的預設鍵盤處理功能,用戶不需要進行任何額外的開發。
例如,可以生成複合控制項,以顯示來自資料庫的客戶地址數據。 此控制項可包括用於顯示資料庫欄位的 DataGridView 控制項、用於處理到數據源的綁定的 BindingSource,以及用於在記錄之間移動的 BindingNavigator 控制項。 可以選擇性地公開數據綁定屬性,還可以將整個控制項打包併在不同應用程式之間重覆使用。 有關這種複合控制項的示例,請參閱如何:應用 Windows 窗體控制項中的特性。
若要創作複合控制項,請從 UserControl 類派生。 基類 UserControl 為子控制項提供了鍵盤路由,並使子控制項可以作為組進行工作。 有關詳細信息,請參閱開發複合 Windows 窗體控制項。

建議
如果為以下情況,則從 UserControl 類繼承:
你想要將多個 Windows 窗體控制項的功能組合到單個可重用單元。
擴展控制項
你可以從任何現有的 Windows 窗體控制項派生繼承的控制項。 使用此方法,你可以保留 Windows 窗體控制項的所有固有功能,然後通過添加自定義屬性、方法或其他功能來擴展該功能。 可以使用此選項重寫基控制項的繪製邏輯,然後通過更改該控制項的外觀來擴展其用戶界面。
例如,可以創建一個由 Button 控制項派生的控制項,並用它來跟蹤用戶的單擊次數。
在某些控制項中,也可以通過重寫基類的 OnPaint 方法為控制項的圖形用戶界面添加自定義外觀。 對於跟蹤單擊次數的擴展按鈕,可以重寫 OnPaint 方法以調用 OnPaint 的基實現,然後在 Button 控制項的工作區的一角繪製單擊計數。

建議
如果為以下情況,則從 Windows 窗體控制項繼承:
大部分所需功能與現有的 Windows 窗體控制項相同。
不需要自定義圖形用戶界面,或者想為現有控制項設計一個新的圖形用戶界面。

自定義控制項
創建控制項的另一種方法是通過從 Control 繼承,從頭開始充分創建一個控制項。 Control 類提供控制項所需的所有基本功能(包括滑鼠和鍵盤處理事件),但不提供特定於控制項的功能或圖形界面。
相比從 UserControl 或現有 Windows 窗體控制項繼承來說,通過從 Control 類繼承來創建控制項需要花費更多心思和精力。 由於用戶還需執行大量的實現,因此,控制項可以具有比複合控制項或擴展控制項更好的靈活性,而且可以使控制項完全滿足自己的需要。
若要實現自定義控制項,必須編寫該控制項的 OnPaint 事件的代碼,以及所需的任何功能特定的代碼。 還可以重寫 WndProc 方法並直接處理視窗消息。 這是創建控制項的最強大的方法,但若要有效地使用此技術,需熟悉 Microsoft Win32® API。
時鐘控制項即是一個自定義控制項,它複製模擬時鐘的外觀和行為。 調用自定義繪製來使指針移動,以響應來自內部 Timer 組件的 Tick 事件。 有關詳細信息,請參閱如何:開發簡單的 Windows 窗體控制項。

建議
如果為以下情況,則從 Control 類繼承:
你想要提供控制項的自定義圖形表示形式。
你需要實現不能通過標準控制項實現的自定義功能。

ActiveX 控制項
儘管 Windows 窗體基礎結構已為承載 Windows 窗體控制項進行了優化,但仍可以使用 ActiveX 控制項。 Visual Studio 中對此任務提供支持。 有關詳細信息,請參閱如何:向 Windows 窗體添加 ActiveX 控制項。

無視窗控制項
Microsoft Visual Basic® 6.0 和 ActiveX 技術支持無視窗控制項。 Windows 窗體中不支持無視窗控制項。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 雙親委派機制:當某個類載入器準備載入一個.class位元組碼文件時,它首先將這個載入任務委派給上一級類載入器,上一級載入器再委派到更上一級類載入器,遞歸這個操作直到最頂級的類載入器。 一、類載入器的類別 在介紹Java的雙親委派機制的時候,不得不提ClassLoader(類載入器) 我們編譯的Java ...
  • 一、分散式鏈路追蹤發展簡介 1.1 分散式鏈路追蹤介紹 關於分散式鏈路追蹤的介紹,可以查看我前面的文章 微服務架構學習與思考(09):分散式鏈路追蹤系統-dapper論文學習(https://www.cnblogs.com/jiujuan/p/16097314.html) 。 這裡的 OpenTel ...
  • 條碼的應用已深入生活和工作的方方面面。在處理條碼時,常需要和各種文檔格式相結合。當需要在文檔中插入、編輯或者刪除條碼時,可藉助於一些專業的類庫工具來實現。本文,以操作PDF文件為例,介紹如何在編輯表格時,向單元格中添加條形碼。 【程式環境】 本次功能測試中,使用 Free Spire.PDF for ...
  • 1 Sentinel主頁 https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E9%A1%B5 1.1 Sentinel介紹 隨著微服務的流行,服務和服務之間的穩定性變得越來越重要。Sentinel 是面向分散式服務架構的流量控制組件,主要以流量為切 ...
  • 前言 dubbo是一款微服務開發框架,它提供了 RPC通信 與 微服務治理 兩大關鍵能力。作為spring cloud alibaba體系中重要的一部分,隨著spring cloud alibaba在國內活躍起來,dubbo也越來越深受各大公司的青睞。本文就來對dubbo的spi機制源碼進行剖析,看 ...
  • ​ 問題描述 我在Eclipse上運行項目的時候,在我用fileUpload上傳圖片,等到下一次Tomcat刷新的時候,這個照片就沒了,而且點擊查看那個文件夾也查看不到有圖片文件。 原因 我後來在網上查詢相關資料發現是Eclipse整 合Tomcat的問題,因為他們整合之後,你用相對路徑上傳的圖片會 ...
  • 用戶 在系統里,用戶是一個核心概念。它代表了一個人的唯一身份標識,除了與角色、團隊、組織架構等有關,甚至還會影響到在同一個界面不同的用戶操作流程與顯示內容都會發生變化,再複雜一點的話,或許在同一個系統內的一個用戶進入到不同產品後的身份也會變化 用戶與角色 用戶可以擁有一個或多個角色,讓角色作為許可權組 ...
  • 當服務端啟動後,但是telnet其監聽的埠卻失敗了。或者當服務端運行了一段時間後,突然其監聽的埠telnet不通了。當類似這樣情況出現時,要如何排查問題所在了? ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...