65.9K
CodeProject 正在变化。 阅读更多。
Home

带分隔符的标签

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.77/5 (17投票s)

2004年11月12日

Zlib

2分钟阅读

viewsIcon

70530

downloadIcon

1657

一个带有文本的简单分隔符。

引言

有时需要在对话框中视觉上分隔控件。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 错误修复。
© . All rights reserved.