InfoBarLite 控件






4.33/5 (11投票s)
2002年9月6日
4分钟阅读

117367

2232
本文展示了如何使用 C# 创建一个 Windows.Forms 控件。
引言
自从微软开始使用一种漂亮的 GUI 风格,在设置窗体顶部显示简要信息以来,我一直想拥有一个自己的。上面显示的截图展示了这样一个控件的示例。我最初用 VB6 创建了这个控件作为 OCX,并在几个项目中使用了它。VB6 版本需要大量使用 Win32 API 函数。然而,为了学习 C# 语法,我决定用这种新语言创建同一个控件,我称之为 InfoBarLite
。开始编码后,我发现用 C# 生活要好得多。
该控件具有一些非常好的功能,可以使事情变得更容易
- 该控件可以同时拥有背景图像和单独的图像。
- 图像可以通过 9 种不同的方式进行对齐。此外,还可以使用 x 和 y 偏移属性来定位图像。
- 提供了两个不同的文本属性,每个属性都可以包含多个由
Environment.NewLine
字符分隔的行。 - 每个文本属性都有自己的
Font
、ForeColor
、OffsetX
和OffsetY
属性。 - 控件的背景色可以是纯色或渐变色。
- 该控件可以为所有边或每个边提供 9 种不同的边框样式。
- 它可以作为标题栏或侧边栏使用。
详细说明
正如下面所示,InfoBarLite
控件派生自 System.Windows.Forms.UserControl
。
public class InfoBarLite : System.Windows.Forms.UserControl
{ // Actual code
...
}
控件中最有趣的部分是 OnPaint
事件,因为这通常是所有者绘制控件的情况。首先,绘制背景信息。此信息由 BackStyle
、BorderSide
和 BoderStyle
属性定义。我想强调的一点是控件的行为。如果 BackStyle
是 Gradient
,则不绘制背景图像。这意味着 BackStyle
属性优先于 BackgroundImage
属性。相反,如果 BackStyle
是 Solid
,则忽略 BackColor
属性。这种行为是设计使然。当然,可以通过修改重写的 OnPaint
事件轻松更改。现在,这是 OnPaint
方法。
/// <summary>
/// Overloaded Paint method
/// </summary>
/// <param name="pe">PaintEventArgs</param>
protected override void OnPaint(PaintEventArgs pe)
{
// First, repaint the base class
base.OnPaint(pe);
Rectangle r = this.ClientRectangle;
// Draw the background and border(s)
switch( this.BackStyle )
{
case BackStyle.Gradient:
LinearGradientBrush gb = new LinearGradientBrush(r,
this.GradientStartColor,
this.GradientEndColor,
this.GradientMode);
if(this.BorderSide == Border3DSide.All)
{
ControlPaint.DrawBorder3D(pe.Graphics, r,
this.BorderStyle, this.BorderSide);
r.Inflate(-2, -2);
pe.Graphics.FillRectangle(gb, r);
}
else
{
pe.Graphics.FillRectangle(gb, r);
ControlPaint.DrawBorder3D(pe.Graphics, r,
this.BorderStyle, this.BorderSide);
}
gb.Dispose();
break;
case BackStyle.Solid:
if(this.BorderSide == Border3DSide.All)
{
ControlPaint.DrawBorder3D(pe.Graphics, r,
this.BorderStyle, this.BorderSide);
r.Inflate(-2, -2);
SolidBrush sb = new SolidBrush(this.BackColor);
pe.Graphics.FillRectangle(sb, r);
sb.Dispose();
}
else
{
ControlPaint.DrawBorder3D(pe.Graphics, r,
this.BorderStyle, this.BorderSide);
}
break;
default:
ControlPaint.DrawBorder3D(pe.Graphics, r,
this.BorderStyle, this.BorderSide);
break;
}
// Set variables for Image and Text drawing
StringFormat fmt = new StringFormat();
fmt.FormatFlags = StringFormatFlags.MeasureTrailingSpaces |
StringFormatFlags.DisplayFormatControl |
StringFormatFlags.FitBlackBox;
fmt.Trimming = StringTrimming.EllipsisCharacter;
// Rectangle variables that will be calculated
RectangleF rImage = new RectangleF(0,0,0,0);
RectangleF rText1 = new RectangleF(0,0,0,0);
RectangleF rText2 = new RectangleF(0,0,0,0);
SizeF sizeText1 = pe.Graphics.MeasureString(this.Text1,
this.Text1Font, ClientRectangle.Size, fmt);
SizeF sizeText2 = pe.Graphics.MeasureString(this.Text2,
this.Text2Font, ClientRectangle.Size, fmt);
// Calculate the rectangles before starting to draw
this.getRects(ref rImage, ref rText1,
sizeText1, ref rText2, sizeText2);
// Draw the image and the texts
if(this.Enabled)
{
int iImageWidth = 0;
if( this.m_Image != null )
{
pe.Graphics.DrawImage(this.m_Image, rImage);
iImageWidth = this.m_Image.Width;
}
SolidBrush sb = new SolidBrush(this.Text1ForeColor);
pe.Graphics.DrawString(this.Text1,
this.Text1Font, sb, rText1, fmt);
sb = new SolidBrush(this.Text2ForeColor);
pe.Graphics.DrawString(this.Text2, this.Text2Font,
sb, rText2, fmt);
sb.Dispose();
}
else
{
if( this.m_Image != null )
ControlPaint.DrawImageDisabled(pe.Graphics,
this.m_Image, (int) rImage.X, (int) rImage.Y,
SystemColors.ControlLight);
ControlPaint.DrawStringDisabled(pe.Graphics,
this.Text1, this.Text1Font,
SystemColors.ControlLight,
rText1,
fmt);
ControlPaint.DrawStringDisabled(pe.Graphics,
this.Text2, this.Text2Font,
SystemColors.ControlLight,
rText2,
fmt);
}
}
用法
使用此控件应该非常简单。只需将其放入窗体,设置所需的属性,即可完成。下面是一个与 Nero 的屏幕非常相似的示例。
图 3 - 一个示例演示屏幕,显示了该控件作为侧边栏和标题栏。
已知问题/限制
有一些问题需要修复和/或添加。
- 当控件用作侧边栏时,文本属性不会旋转(垂直)绘制,但这是设计使然。
- 从
UserControl
类继承的Font
属性不应向用户显示。目前,我不知道如何做到这一点;因此,任何建议都将受到赞赏。 - 当在设计模式下的属性窗口中更改
Enabled
属性时,此更改不会反映到控件上。另一方面,如果通过代码更改此属性,控件将按预期运行。再次,我需要有关此问题的建议。 - 最后一个限制是该控件不支持国际化。在 VS IDE 中,如果将
Form
的Localizable
属性设置为True
,IDE 会自动添加代码以检索本地控件(随 VS.NET 一起提供)的正确文本,这些文本将通过资源管理器反映CurrentCulture
。我认为这是本地化应用程序的最简单方法。目前,InfoBarLite
与 IDE 协作不佳,无法完成此任务。如果有人知道如何做到这一点并提供解决方案,我可以更新该控件以使所有人受益。
结论
希望 InfoBarLite
控件能像使我自己的生活一样,使我的同事开发者们的(生活)更轻松。它还将允许您添加一个非常好的用户界面功能,帮助您提高最终用户的体验。如果您查看图 1,此控件将提高我们为用户创建的窗体的可理解性,因为用户现在将获得有关需要他们做什么的更具描述性的信息。传统上,这类信息显示在 StatusBar
控件中。然而,大多数用户并不满意,至少我的用户不满意,因为他们被迫阅读如此小的字体。InfoBarLite
控件试图解决上述可用性问题。它可以显示两种不同风格的文本和一个图像。图像可能比文本更能描述需要完成的任务,因为大多数人倾向于不阅读说明。建议在对话框中使用它,当然,这取决于您。