本文介紹自定義控件,並說明它們與使用者控件的不同。 自定義控制項不提供可視化設計介面,並依賴使用者提供的程式代碼來繪製自己。 這與使用者控件不同,這些控件提供可視化設計介面,將多個控件分組成單一可重複使用的單位。
當現有的控件或使用者控件未接近提供您需要的UI或互動性時,會使用自定義控件。 它們需要您更努力才能完全實作。 Windows Forms 仍然提供鍵盤和滑鼠處理,但任何功能或動作都需要您自行實作。 自定義控制項沒有提供設計介面,因為所有繪圖都是透過 OnPaint 方法中的程式碼完成。 元件,例如 Timer,仍然可以透過非視覺設計介面來新增。
基類
建立自定義控件時,有兩個基類可供選擇:
-
這是其他 Windows Forms 控制件所使用的相同基類。 您可以直接控制控制控制項的輸入和輸出。
System.Windows.Forms.ScrollableControl
某些 Windows Forms 控制件會使用此基類。 此類別透過增加內容捲動功能來擴展
Control。
除非您需要卷動自定義控件的內容,否則請使用 Control 作為基類。
繼承的功能
由於自定義控件的基類是 Control,因此您會自動繼承所有控件共用的 Windows Forms 功能。 以下是您使用自訂控制項取得的一些功能:
- 鍵盤和滑鼠輸入。
- 配置行為,例如錨定和停駐。
- 支援索引標籤。
- 最小和最大大小限制。
繪圖
繪圖,即繪製控制項的畫面,是透過覆寫OnPaint方法來實現的。 如需了解有關控件的繪製方式的詳細資訊,請參閱 在控件上繪畫和繪圖。
當您使用 Visual Studio 範本建立自訂控制項時,OnPaint 方法會自動為您覆蓋。 範本會執行此動作,因為您必須撰寫程式代碼來繪製控件。 以下是範本產生的範例:
public partial class CustomControl1 : Control
{
public CustomControl1()
{
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
}
Public Class CustomControl1
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
MyBase.OnPaint(e)
'Add your custom paint code here
End Sub
End Class
自定義控件會使用 OnPaint 方法繪製。 此方法的單一 PaintEventArgs 自變數是 物件,可提供轉譯控件所需的所有資訊和功能。
PaintEventArgs 提供用於轉譯控件的兩個屬性:
PaintEventArgs.ClipRectangle—表示需要重新繪製之控件的一部分。 這可以是整個控件或控件的一部分。
Graphics—代表控件的圖形介面。 它提供數個圖形導向的物件和方法,提供繪製控件所需的功能。
每當在畫面上繪製或刷新控制項時,會呼叫OnPaint方法,而PaintEventArgs.ClipRectangle物件代表進行繪製的矩形區域。 如果需要重新整理整個控件, PaintEventArgs.ClipRectangle 則表示整個控件的大小。 如果只需要重新整理控件的一部分,它就只代表需要重新繪製的區域。 例如,當使用者介面中的一個控件部分被另一個控件遮住,並且該遮蔽的控件被移走後,必須重新繪製露出的下方控件部分。
當控制項首次被繪製或每當它被標記為無效時,控制項方法中的 OnPaint 程式碼將會執行。 若要確保您的控件每次重設大小都會重新繪製,請將下列這一行新增至控件的建構函式:
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.ResizeRedraw, True)
範例
下列代碼段是自定義控件,可呈現控件邊緣的多個彩色矩形。
protected override void OnPaint(PaintEventArgs pe)
{
Rectangle rect = this.ClientRectangle;
// Bring the width/height in by 1 pixel so the rectangle is drawn inside the control.
// Otherwise, it kind of overlaps the outside edge.
rect.Width -= 1;
rect.Height -= 1;
Pen[] colorPens = new Pen[] { Pens.Blue, Pens.BlueViolet,
Pens.AliceBlue, Pens.CornflowerBlue,
Pens.Cyan, Pens.DarkCyan };
foreach (Pen pen in colorPens)
{
pe.Graphics.DrawRectangle(pen, rect);
rect.Inflate(-1, -1);
}
// Raise the Paint event so users can custom paint if they want.
base.OnPaint(pe);
}
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
Dim rect As Rectangle = Me.ClientRectangle
'Bring the width/height in by 1 pixel so the rectangle is drawn inside the control.
'Otherwise, it kind of overlaps the outside edge.
rect.Width -= 1
rect.Height -= 1
Dim colorPens As Pen() = {Pens.Blue, Pens.BlueViolet,
Pens.AliceBlue, Pens.CornflowerBlue,
Pens.Cyan, Pens.DarkCyan}
For Each curPen As Pen In colorPens
e.Graphics.DrawRectangle(curPen, rect)
rect.Inflate(-1, -1)
Next
'Raise the Paint event so users can custom paint if they want.
MyBase.OnPaint(e)
End Sub
先前的程式代碼會建立看起來像下圖的控制項:
背景
請注意,控件的背景會以 SystemColors.Control 色彩繪製,即使程式 OnPaint 代碼未清除或以色彩填滿控件。 在OnPaintBackground(PaintEventArgs)被呼叫之前,背景其實是由OnPaint方法繪製的。 重寫 OnPaintBackground 以處理控制項的背景繪製。 此方法的預設實作是分別繪製由BackColor屬性設定的色彩和由BackgroundImage屬性設定的影像。