如何:开发简单的 Windows 窗体控件
本部分演示创建自定义 Windows 窗体控件的关键步骤。 本演练中开发的简单控件允许更改 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 方法来重绘控件。 在基类 Control 中定义 Invalidate。
重写从 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
为控件提供属性。 特性让视觉设计器能够在设计时适当显示控件及其属性和事件。 以下代码片段将特性应用于
TextAlignment
属性。 在诸如 Visual Studio 的设计器中,Category 特性(在代码片段中显示)会让属性显示在逻辑类别下。 如果选择了TextAlignment
属性,Description 特性会使描述性字符串显示在“属性”窗口的底部。 有关属性的详细信息,请参阅组件的设计时属性。[ Category("Alignment"), Description("Specifies the alignment of text.") ]
<Category("Alignment"), Description("Specifies the alignment of text.")> _ Public Property TextAlignment() As ContentAlignment
(可选)为控件提供资源。 可通过使用编译器选项(对于 C#,为
/res
)将资源和控件进行打包,从而为控件提供资源(如位图)。 在运行时,可以使用 ResourceManager 类的方法检索资源。 有关创建和使用资源的详细信息,请参阅桌面应用中的资源。编译和部署控件。 要编译和部署
FirstControl,
,请执行以下步骤:将以下示例中的代码保存到源文件(如 FirstControl.cs 或 FirstControl.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
声明允许代码直接作为 Control 访问来自 System.Windows.Forms 的类 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