HOW TO:開發簡單的 Windows Form 控制項
更新:2007 年 11 月
本章節逐步為您解說撰寫自訂 Windows Form 控制項的重要步驟。這個逐步解說開發的簡單控制項允許您變更其 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 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
// 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;
當您設定會變更控制項視覺顯示的屬性時,您必須叫用 Invalidate 方法來重繪控制項。Invalidate 是定義於 Control 基底類別中。
覆寫保護的 (Protected) OnPaint 方法 (繼承自 Control),為控制項提供呈現邏輯。如果您不覆寫 OnPaint,您的控制項將無法自行繪圖。在下列程式碼片段中,OnPaint 方法以 alignmentValue 欄位所指定的對齊顯示繼承自 Control 的 Text 屬性。
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
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); }
提供屬性給您的控制項。屬性讓視覺設計工具能夠在設計階段適當顯示您的控制項和它的屬性和事件。下列程式碼片段套用屬性於 TextAlignment 屬性。在設計工具 (例如 Visual Studio) 中,Category 屬性 (Attribute)(顯示於程式碼片段) 會造成屬性 (Property) 顯示在邏輯分類之下。Description 屬性 (Attribute) 在 TextAlignment 屬性 (Property) 選取時,會導致說明字串顯示於 [屬性] 視窗底部。如需屬性 (Attribute) 的詳細資訊,請參閱元件的設計階段屬性。
<Category("Alignment"), Description("Specifies the alignment of text.")> _ Public Property TextAlignment() As ContentAlignment
[ Category("Alignment"), Description("Specifies the alignment of text.") ]
(選擇性) 提供資源給您的控制項。您可以使用編譯器選項 (在 C# 中為 /res),將資源與控制項一起封裝 (Package),以提供資源 (例如點陣圖) 給控制項。在執行階段時,可以使用 ResourceManager 類別的方法來擷取資源。如需建立和使用資源的詳細資訊,請參閱應用程式中的資源。
編譯和部署您的控制項。若要編譯和部署 FirstControl,,請執行下列步驟。
儲存下列範例中的程式碼至原始程式檔 (例如 FirstControl.cs 或 FirstControl.vb)。
將原始程式碼編譯成組件 (Assembly),並將它儲存在您應用程式的目錄。若要達成這點,請從含有原始程式檔的目錄中執行下列命令。
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 選項會提供您程式碼所參考組件的名稱。在這個範例中,您建立只有您的應用程式可以使用的私用 (Private) 組件。因此您必須將它儲存於您應用程式的目錄。如需封裝和部署散發的控制項的詳細資訊,請參閱部署 .NET Framework 應用程式。
下列範例示範 FirstControl 的程式碼。控制項被封入在命名空間 CustomWinControls 中。命名空間提供相關型別的邏輯群組。您可以在新的或現有命名空間中建立您的控制項。在 C# 中,using 宣告 (在 Visual Basic 中為 Imports) 允許型別從命名空間來存取,而不需使用型別的完整名稱。在下列範例中,using 宣告允許程式碼僅用 Control 從 System.Windows.Forms 存取 Control 類別,而不必使用完整名稱 System.Windows.Forms.Control。
Imports System
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
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);
}
}
}
在網頁上使用自訂控制項
下列範例示範使用 FirstControl 的簡單表單。它建立三個 FirstControl 的執行個體,各個都有不同的 TextAlignment 屬性值。
編譯和執行這個範例
儲存下列範例中的程式碼至原始程式檔 (簡單 Form.cs 或 簡單 Forms.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 的組件。這個組件必須位於存取它的表單 (簡單 Form.cs 或 簡單 Forms.vb) 的原始程式檔的相同目錄。
使用下列命令執行簡單的 Form.exe。
SimpleForm
Imports System
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
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());
}
}
}