操作說明:開發簡單的 Windows Forms 控制項
本節將逐步引導您完成撰寫自訂 Windows Forms 控制項的重要步驟。 本逐步解說中開發的簡單控制項允許變更其 Text 屬性的對齊方式。 它不會引發或處理事件。
建立簡單自訂控制項
定義衍生自 System.Windows.Forms.Control 的類別。
Public Class FirstControl Inherits Control End Class
public class FirstControl:Control {}
定義屬性。 (您不需定義屬性,因為控制項會從 Control 類別繼承許多屬性,但大部分自訂控制項通常會定義其他屬性。)下列程式碼片段會定義名為
TextAlignment
的屬性,FirstControl
會使用這個屬性來格式化繼承自 Control 的 Text 屬性顯示。 如需有關定義屬性的詳細資訊,請參閱屬性概觀。// ContentAlignment is an enumeration defined in the System.Drawing // namespace that specifies the alignment of content on a drawing // surface. private ContentAlignment alignmentValue = ContentAlignment.MiddleLeft;
' ContentAlignment is an enumeration defined in the System.Drawing ' namespace that specifies the alignment of content on a drawing ' surface. Private alignmentValue As ContentAlignment = ContentAlignment.MiddleLeft <Category("Alignment"), Description("Specifies the alignment of text.")> _ Public Property TextAlignment() As ContentAlignment Get Return alignmentValue End Get Set alignmentValue = value ' The Invalidate method invokes the OnPaint method described ' in step 3. Invalidate() End Set End Property
當您設定屬性來變更控制項的視覺效果顯示時,您必須叫用 Invalidate 方法來重新繪製控制項。 Invalidate 會在 Control 基底類別中進行定義。
覆寫繼承自 Control 的受保護 OnPaint 方法,為控制項提供轉譯邏輯。 如果您未覆寫 OnPaint,則控制項將無法自行繪製。 在下列程式碼片段中,OnPaint 方法會顯示繼承自 Control 的 Text 屬性,以及
alignmentValue
欄位所指定的對齊方式。protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); StringFormat style = new StringFormat(); style.Alignment = StringAlignment.Near; switch (alignmentValue) { case ContentAlignment.MiddleLeft: style.Alignment = StringAlignment.Near; break; case ContentAlignment.MiddleRight: style.Alignment = StringAlignment.Far; break; case ContentAlignment.MiddleCenter: style.Alignment = StringAlignment.Center; break; } // Call the DrawString method of the System.Drawing class to write // text. Text and ClientRectangle are properties inherited from // Control. e.Graphics.DrawString( Text, Font, new SolidBrush(ForeColor), ClientRectangle, style); }
Protected Overrides Sub OnPaint(e As PaintEventArgs) MyBase.OnPaint(e) Dim style As New StringFormat() style.Alignment = StringAlignment.Near Select Case alignmentValue Case ContentAlignment.MiddleLeft style.Alignment = StringAlignment.Near Case ContentAlignment.MiddleRight style.Alignment = StringAlignment.Far Case ContentAlignment.MiddleCenter style.Alignment = StringAlignment.Center End Select ' Call the DrawString method of the System.Drawing class to write ' text. Text and ClientRectangle are properties inherited from ' Control. e.Graphics.DrawString( _ me.Text, _ me.Font, _ New SolidBrush(ForeColor), _ RectangleF.op_Implicit(ClientRectangle), _ style) End Sub
為您的控制項提供屬性 (attribute)。 屬性可讓視覺化設計工具在設計階段適當地顯示您的控制項及其屬性與事件。 下列程式碼片段會將屬性 (attribute) 套用至
TextAlignment
屬性 (property)。 在 Visual Studio 之類的設計工具中,Category 屬性 (如程式碼片段中所示) 會導致屬性顯示在邏輯類別之下。 Description 屬性會在選取TextAlignment
屬性時,在 [屬性] 視窗底部顯示描述性字串。 如需屬性的詳細資訊,請參閱元件的設計階段屬性。[ Category("Alignment"), Description("Specifies the alignment of text.") ]
<Category("Alignment"), Description("Specifies the alignment of text.")> _ Public Property TextAlignment() As ContentAlignment
(選擇性) 為您的控制項提供資源。 您可以使用編譯器選項 (
/res
適用於 C#) 來封裝資源與您的控制項,為您的控制項提供資源 (例如點陣圖)。 在執行階段,可以使用 ResourceManager 類別的方法來擷取資源。 如需有關建立和使用資源的詳細資訊,請參閱桌面應用程式中的資源。編譯及部署您的控制項。 若要編譯及部署
FirstControl,
,請執行下列步驟︰將下列範例中的程式碼儲存至原始程式檔 (SimpleForm.cs 或 SimpleForms.vb)。
將原始程式碼編譯成組件,並將它儲存在您應用程式的目錄中。 若要達成此目的,請從包含原始程式檔的目錄執行下列命令。
vbc -t:library -out:[path to your application's directory]/CustomWinControls.dll -r:System.dll -r:System.Windows.Forms.dll -r:System.Drawing.dll FirstControl.vb
csc -t:library -out:[path to your application's directory]/CustomWinControls.dll -r:System.dll -r:System.Windows.Forms.dll -r:System.Drawing.dll FirstControl.cs
/t:library
編譯器選項會告知編譯器您所建立的組件是程式庫 (而不是可執行檔)。/out
選項指定組件的路徑和名稱。/r
選項會提供您的程式碼所參考的組件名稱。 在此範例中,您會建立只有您的應用程式可以使用的私人組件。 因此,您必須將它儲存在您應用程式的目錄中。 如需有關封裝和部署控制項以供散發的詳細資訊,請參閱部署。
下列範例顯示 FirstControl
的程式碼。 控制項會包含在 CustomWinControls
命名空間中。 命名空間會提供相關類型的邏輯分組。 您可以在新的或現有命名空間中建立您的控制項。 在 C# 中,using
宣告 (在 Visual Basic 中為 Imports
) 允許從命名空間存取類型,而不需使用完整的類型名稱。 在下列範例中,using
宣告允許程式碼從 System.Windows.Forms 直接存取 Control 類別做為 Control,而不必使用完整名稱 System.Windows.Forms.Control。
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
namespace CustomWinControls
{
public class FirstControl : Control
{
public FirstControl()
{
}
// ContentAlignment is an enumeration defined in the System.Drawing
// namespace that specifies the alignment of content on a drawing
// surface.
private ContentAlignment alignmentValue = ContentAlignment.MiddleLeft;
[
Category("Alignment"),
Description("Specifies the alignment of text.")
]
public ContentAlignment TextAlignment
{
get
{
return alignmentValue;
}
set
{
alignmentValue = value;
// The Invalidate method invokes the OnPaint method described
// in step 3.
Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
StringFormat style = new StringFormat();
style.Alignment = StringAlignment.Near;
switch (alignmentValue)
{
case ContentAlignment.MiddleLeft:
style.Alignment = StringAlignment.Near;
break;
case ContentAlignment.MiddleRight:
style.Alignment = StringAlignment.Far;
break;
case ContentAlignment.MiddleCenter:
style.Alignment = StringAlignment.Center;
break;
}
// Call the DrawString method of the System.Drawing class to write
// text. Text and ClientRectangle are properties inherited from
// Control.
e.Graphics.DrawString(
Text,
Font,
new SolidBrush(ForeColor),
ClientRectangle, style);
}
}
}
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Public Class FirstControl
Inherits Control
Public Sub New()
End Sub
' ContentAlignment is an enumeration defined in the System.Drawing
' namespace that specifies the alignment of content on a drawing
' surface.
Private alignmentValue As ContentAlignment = ContentAlignment.MiddleLeft
<Category("Alignment"), Description("Specifies the alignment of text.")> _
Public Property TextAlignment() As ContentAlignment
Get
Return alignmentValue
End Get
Set
alignmentValue = value
' The Invalidate method invokes the OnPaint method described
' in step 3.
Invalidate()
End Set
End Property
Protected Overrides Sub OnPaint(e As PaintEventArgs)
MyBase.OnPaint(e)
Dim style As New StringFormat()
style.Alignment = StringAlignment.Near
Select Case alignmentValue
Case ContentAlignment.MiddleLeft
style.Alignment = StringAlignment.Near
Case ContentAlignment.MiddleRight
style.Alignment = StringAlignment.Far
Case ContentAlignment.MiddleCenter
style.Alignment = StringAlignment.Center
End Select
' Call the DrawString method of the System.Drawing class to write
' text. Text and ClientRectangle are properties inherited from
' Control.
e.Graphics.DrawString( _
me.Text, _
me.Font, _
New SolidBrush(ForeColor), _
RectangleF.op_Implicit(ClientRectangle), _
style)
End Sub
End Class
在表單上使用自訂控制項
下列範例顯示一個使用 FirstControl
的簡單表單。 它會建立三個 FirstControl
執行個體,各有不同的 TextAlignment
值。
若要編譯和執行這個範例
將下列範例中的程式碼儲存至原始程式檔 (SimpleForm.cs 或 SimpleForms.vb)。
從包含原始程式檔的目錄執行下列命令,將原始程式檔編譯成可執行檔的組件。
vbc -r:CustomWinControls.dll -r:System.dll -r:System.Windows.Forms.dll -r:System.Drawing.dll SimpleForm.vb
csc -r:CustomWinControls.dll -r:System.dll -r:System.Windows.Forms.dll -r:System.Drawing.dll SimpleForm.cs
CustomWinControls.dll 是包含
FirstControl
類別的組件。 此組件所在的目錄必須與存取該組件之表單的原始程式檔 (SimpleForm.cs 或 SimpleForms.vb) 相同。使用下列命令執行 SimpleForm.exe。
SimpleForm
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
namespace CustomWinControls
{
public class SimpleForm : System.Windows.Forms.Form
{
private FirstControl firstControl1;
private System.ComponentModel.Container components = null;
public SimpleForm()
{
InitializeComponent();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
private void InitializeComponent()
{
this.firstControl1 = new FirstControl();
this.SuspendLayout();
//
// firstControl1
//
this.firstControl1.BackColor = System.Drawing.SystemColors.ControlDark;
this.firstControl1.Location = new System.Drawing.Point(96, 104);
this.firstControl1.Name = "firstControl1";
this.firstControl1.Size = new System.Drawing.Size(75, 16);
this.firstControl1.TabIndex = 0;
this.firstControl1.Text = "Hello World";
this.firstControl1.TextAlignment = System.Drawing.ContentAlignment.MiddleCenter;
//
// SimpleForm
//
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.firstControl1);
this.Name = "SimpleForm";
this.Text = "SimpleForm";
this.ResumeLayout(false);
}
[STAThread]
static void Main()
{
Application.Run(new SimpleForm());
}
}
}
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Public Class SimpleForm
Inherits System.Windows.Forms.Form
Private firstControl1 As FirstControl
Private components As System.ComponentModel.Container = Nothing
Public Sub New()
InitializeComponent()
End Sub
Private Sub InitializeComponent()
Me.firstControl1 = New FirstControl()
Me.SuspendLayout()
'
' firstControl1
'
Me.firstControl1.BackColor = System.Drawing.SystemColors.ControlDark
Me.firstControl1.Location = New System.Drawing.Point(96, 104)
Me.firstControl1.Name = "firstControl1"
Me.firstControl1.Size = New System.Drawing.Size(75, 16)
Me.firstControl1.TabIndex = 0
Me.firstControl1.Text = "Hello World"
Me.firstControl1.TextAlignment = System.Drawing.ContentAlignment.MiddleCenter
'
' SimpleForm
'
Me.ClientSize = New System.Drawing.Size(292, 266)
Me.Controls.Add(firstControl1)
Me.Name = "SimpleForm"
Me.Text = "SimpleForm"
Me.ResumeLayout(False)
End Sub
<STAThread()> _
Shared Sub Main()
Application.Run(New SimpleForm())
End Sub
End Class