目标闪烁板 (GDI+ 轻松实现)
展示了如何仅使用 GDI+ 轻松创建 WinForms 用户控件。

引言
本文将向您展示如何使用 System.Drawing
类(也称为 GDI+)创建一个 .NET UserControl
,用于显示类似于机场旧的到达/出发板的信息。当每一行发生变化时,该板将通过字母表闪烁以显示新条目。
本文的目的不是为了教你如何成为 GDI+ 专家。它实际上是为了表明 GDI+ 并没有许多人想象的那么难。它的目的是鼓励开发人员在现有控件无法满足需求,或者当您想为您的 Winforms UI 演示添加一些润色时,创建自定义控件。
Using the Code
一旦您将 AirportDepartureBoard
控件添加到您的表单中,您会发现您无法向控件添加或删除行。因此,更改行文本的唯一方法是调用控件的 UpdateRow
方法。最好在初始化表单时将闪烁设置为 Flicker.No
。这将避免减慢表单的加载时间。
MyDepartureBoard.UpdateRow(0, “Hello World” Flicker.No);
初始化后,要使闪烁生效,请在更新行的文本时将 Flicker
参数设置为 Flicker.Yes
。
MyDepartureBoard.UpdateRow(1, “It’s a beautiful day” Flicker.Yes);
下载源代码中的 AirportDepartureBoard
控件是使用 Croll.Windows.Forms.DestinationBoard
控件的一个例子,该控件完成了大部分工作。DestinationBoard
控件具有许多您可以在设计时或运行时设置的属性。这些是 BoardBackColor
, BoardRowDividerColor
和 BoardFlickerHingeColor
。您会发现,当您在设计时更改这些属性时,更改将反映在表单设计器中(这很好)。值得注意的是,该控件仅使用 BoardBackColor
显示整行。控件底部的任何剩余空间将使用控件的 BackColor
属性显示。
使用 GDI+ 创建 UserControl
GDI+ 听起来有点吓人。它给人一种您将不得不进行一些底层编程才能使用 GDI+ 的印象。但事实并非如此,因为 .NET Framework 已经将 GDI+ 功能抽象到 System.Drawing
命名空间中,这使得开发人员的生活变得更加轻松和简单。System.Drawing
命名空间的核心是 Graphics
对象。Graphics
具有许多用于绘图的方法。此演示将突出显示在创建您自己的 UserControl
时使用的一些更简单的方法。下面是一个代码片段,它使用了两个简单的图形方法 FillRectangle
和 DrawLine
。
private void PaintPanel()
{
//Get the control's Graphics object used to paint
Graphics g = this.CreateGraphics();
// Used to paint the row dividers
Pen dividerPen = new Pen(this.boardRowDividerColor);
// Used to paint the hinge in the middle of each row
Pen hingePen = new Pen(this.boardFlickerHingeColor);
// Paint the control with the board's BoardBackColor
g.FillRectangle(new SolidBrush(this.boardBackColor), 0, 0,
base.Width, this.rowCount * this.rowHeight);
// Paint row dividers
for (int i = 0; i <= this.rowCount; i++)
{
g.DrawLine(dividerPen, 0, i * this.rowHeight,
base.Width, i * this.rowHeight);
}
// Paint flicker hinge lines
for (int i = 0; i < this.rowCount; i++)
{
g.DrawLine(hingePen, 0, i * this.rowHeight + (this.rowHeight / 2) + 1,
base.Width, i * this.rowHeight + (this.rowHeight / 2) + 1);
}
// Paint the text values for each row
for (int i = 0; i < rows.Count; i++)
{
PaintRow(new PaintRowParameters(i, Flicker.No, rows[i]));
}
}
在下一个代码片段中,您还将注意到 DrawRectangle
和 DrawString
方法的使用。所有这些方法都命名得非常好,无需解释,这使得 System.Drawing
命名空间相对直观。同样重要的是 Brush
es 的使用。在这种情况下,使用了简单的 SolidBrush
,但是可以使用各种 brush
es 来真正让您的新控件栩栩如生。还应该注意的是,许多对象需要释放,所以不要忘记在使用完对象后释放它们。
private void PaintCharacter(char c, int colIndex, int rowIndex)
{
Graphics g = this.CreateGraphics();
SolidBrush brush = new SolidBrush(ForeColor); //Used to DrawString
// Used to paint the hinge in the middle of each character
Pen pen = new Pen(this.boardFlickerHingeColor);
try
{
int x = (this.colWidth * colIndex);
int y = (this.rowHeight * rowIndex) + 1;
Rectangle topHalfRect = new Rectangle(x, y, this.colWidth,
(this.rowHeight / 2) - 1);
Rectangle fullRect = new Rectangle(x, y, this.colWidth, this.rowHeight - 1);
// Just paint the top half of the character first to give
// the impression that the flap is flicking over
g.FillRectangle(new SolidBrush(this.boardBackColor), topHalfRect);
g.DrawString(c.ToString(), this.Font, brush, topHalfRect);
g.DrawLine(pen, x, y + (this.rowHeight / 2), x +
this.colWidth, y + (this.rowHeight / 2));
// Now paint the whole character
g.FillRectangle(new SolidBrush(this.boardBackColor), fullRect);
g.DrawString(c.ToString(), this.Font, brush, fullRect);
g.DrawLine(pen, x, y + (this.rowHeight / 2), x +
this.colWidth, y + (this.rowHeight / 2));
}
finally
{
g.Dispose();
brush.Dispose();
pen.Dispose();
}
}
如您所见,不需要火箭科学,不需要底层编程。对于我认为相当酷的控件来说,代码相当简单。当然,这只是触及了 GDI+ 可以实现的功能的皮毛,但它表明对于大多数自定义控件,您所需要的只是一些想象力。
有用的提示
在使用 System.Drawing
空间,或者更确切地说是绘制图表时,您会遇到很多 x
和 y
参数。记住什么是 x
和什么是 y
的简单方法就像阅读此页面一样简单。首先您横向阅读 (x
),然后向下阅读 (y
)。
历史
- 2009年9月7日:初始版本