带分隔符的标签






4.77/5 (17投票s)
一个带有文本的简单分隔符。
引言
有时需要在对话框中视觉上分隔控件。GroupBox
是一个解决方案,但如果你只想在 Visual Studio 中的一些选项对话框中看到一条带有标签的水平 3D 线,它就不合适了。一种可能的解决方案是创建一个额外的空标签,并将 BorderStyle
设置为 Fixed3D
,并将 Height
设置为 2。但是,这种方法很麻烦,因为你必须注意控件的放置顺序。此外,如果你要更改标签文本(例如,在本地化应用程序时)或文本对齐方式,你将不得不调整/重新定位控件。因此,我创建了这个简单的标签,它负责处理这些细节。
背景
关于自定义控件创建的细节已经在其他地方解释过了(例如,在优秀的循序渐进的教程 Divider Panel - A tutorial on creating a custom Windows Forms control from Start to Toolbox 中)。因此,我不会详细介绍它们,而只会概述一些具体要点。
LabelWithDivider
控件继承自 Label
类,仅重写了它的 OnPaint
方法。在这个方法中,首先绘制线条,然后调用基类的 OnPaint
方法来处理文本的绘制。
protected override void OnPaint(PaintEventArgs e) {
PlaceLine(e.Graphics);
base.OnPaint(e);
}
方法调用的顺序实际上并不重要,因为 PlaceLine
方法会根据文本长度以及其水平和垂直对齐方式来计算线条的位置和长度。
protected void PlaceLine(Graphics g) {
// evaluates text size
SizeF textSize = g.MeasureString(this.Text, this.Font);
int x0 = 0; // first point x-coordinate
int x1 = this.Width; // second point x-coordinate
// for different horizontal alignments recalculates x-coordinates
switch (GetHorizontalAlignment()) {
case HorizontalAlignment.Left:
x0 = (int)textSize.Width + m_gap;
break;
case HorizontalAlignment.Right:
x1 = this.Width - (int)textSize.Width - m_gap;
break;
case HorizontalAlignment.Center:
x1 = (this.Width - (int)textSize.Width) / 2 - m_gap;
break;
}
int y = (int)textSize.Height / 2;
// for different vertical alignments recalculates y-coordinate
if (TextAlign == ContentAlignment.MiddleLeft
|| TextAlign == ContentAlignment.MiddleCenter
|| TextAlign == ContentAlignment.MiddleRight)
y = this.Height / 2;
else if (TextAlign == ContentAlignment.BottomLeft
|| TextAlign == ContentAlignment.BottomCenter
|| TextAlign == ContentAlignment.BottomRight)
y = this.Height - (int)(textSize.Height / 2) - 2;
Draw3DLine(g, x0, y, x1, y);
// for centered text, two line sections have to be drawn
if (TextAlign == ContentAlignment.TopCenter
|| TextAlign == ContentAlignment.MiddleCenter
|| TextAlign == ContentAlignment.BottomCenter) {
x0 = (this.Width + (int)textSize.Width) / 2 + m_gap;
x1 = this.Width;
Draw3DLine(g, x0, y, x1, y);
}
}
protected HorizontalAlignment GetHorizontalAlignment() {
if (TextAlign == ContentAlignment.TopLeft
|| TextAlign == ContentAlignment.MiddleLeft
|| TextAlign == ContentAlignment.BottomLeft) {
if (RightToLeft == RightToLeft.Yes)
return HorizontalAlignment.Right;
else
return HorizontalAlignment.Left;
}
if (TextAlign == ContentAlignment.TopRight
|| TextAlign == ContentAlignment.MiddleRight
|| TextAlign == ContentAlignment.BottomRight) {
if (RightToLeft == RightToLeft.Yes)
return HorizontalAlignment.Left;
else
return HorizontalAlignment.Right;
}
return HorizontalAlignment.Center;
}
protected void Draw3DLine(Graphics g, int x1, int y1, int x2, int y2) {
g.DrawLine(SystemPens.ControlDark, x1, y1, x2, y2);
g.DrawLine(SystemPens.ControlLightLight, x1, y1+1, x2, y2+1);
}
m_gap
在上面的代码中是文本和线条之间的可选间隙,可以通过 Gap
属性将其设置为非零值。
public int Gap {
get { return m_gap; }
set {
m_gap = value;
Invalidate();
}
}
请注意,setter 调用 Invalidate
以确保在值更改时在视觉设计器中重新绘制控件。
使用代码
控件已放置在类库中(LabelWithDivider.dll),并且已设置所有必需的属性,以便可以将控件添加到工具箱并简单地拖放到窗体上。Gap
属性在外观类别中可用。最后但并非最不重要的一点:LabelWitDivider
放置在 System.Windows.Forms
命名空间中。
历史
- 2004 年 11 月 12 日:版本 1.0
- 2004 年 11 月 13 日:版本 1.1:
LeftToRight
错误修复。