以下代碼實現自定義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 窗體中不支持無視窗控制項。