本文介绍了自定义控件,并介绍了它们与用户控件的区别。 自定义控件不提供视觉设计界面,依靠用户提供的代码进行绘制。 此设计不同于用户控件,这些控件提供可视化设计图面,用于将多个控件分组到单个可重用单元中。
当现有控件或用户控件不接近提供所需的 UI 或交互性时,请使用自定义控件。 你需要付出更多努力才能完全实现。 Windows 窗体仍然提供键盘和鼠标处理,但您需要实现任何特定的处理行为。 自定义控件不包含设计界面,因为所有绘图都是通过 OnPaint 方法中的代码完成的。 你仍然可以通过非可视化设计界面添加组件,例如Timer。
基类
创建自定义控件时,请从两个基类中进行选择:
-
此基类与其他 Windows 窗体控件使用的类相同。 直接控制控件的输入和输出。
System.Windows.Forms.ScrollableControl
某些 Windows 窗体控件使用此基类。 它通过添加滚动内容功能来扩展
Control。
除非需要滚动自定义控件的内容,否则请使用 Control 基类。
继承的功能
由于自定义控件的基类是 Control,因此会自动继承由所有控件共享的 Windows 窗体功能。 下面是使用自定义控件获取的一些功能:
- 键盘和鼠标输入。
- 布局行为,例如定位和停靠。
- 支持标签导航。
- 最小和最大大小限制。
画
绘制是指绘制控件的视觉外观。 可以通过重写 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 属性设置的图像。