Click here to Skip to main content
Click here to Skip to main content

Label with Divider

By , 14 Nov 2004
Rate this:
Please Sign up or sign in to vote.

Introduction

Sometimes it is necessary to visually separate controls in a dialog. GroupBox is one solution, but it is not appropriate if you just want a horizontal 3D line with a label like in some Options dialogs in Visual Studio. One possible solution is to create an additional empty label with BorderStyle set to Fixed3D and Height set to 2. However, this approach is cumbersome because you must take care of control placement order. Moreover, if you are going to change the label text (e.g., when localizing the application) or text alignment, you'll have to resize/reposition controls. Therefore, I have created this simple label that takes care of such details.

Background

Details regarding custom control creation has been explained elsewhere (e.g., in excellent step-by-step tutorial Divider Panel - A tutorial on creating a custom Windows Forms control from Start to Toolbox). Therefore, I will not go through them but only outline some specific points.

LabelWithDivider control inherits the Label class, overriding only its OnPaint method. In this method, line is drawn first, and then base class' OnPaint method is called that takes care of drawing the text:

protected override void OnPaint(PaintEventArgs e) {
    PlaceLine(e.Graphics);
    base.OnPaint(e);
}

The order of method calls is actually not important since PlaceLine method calculates position and length of the line taking in account the text length as well as its horizontal and vertical alignments:

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 in the above code is the optional gap between text and line, which can be set to a non-zero value by Gap property:

public int Gap {
    get { return m_gap; }
    set { 
        m_gap = value; 
        Invalidate();
    }
}

Note that setter calls Invalidate to ensure control is redrawn in the visual designer on value change.

Using the code

Control has been placed into class library (LabelWithDivider.dll) and all required attributes are set so that control can be added to toolbox and simply dragged and dropped onto a form. Gap property is available in Appearance category. And last but not least: LabelWitDivider is placed into System.Windows.Forms namespace.

History

  • November 12, 2004: ver. 1.0
  • November 13, 2004: ver. 1.1: LeftToRight bugfix.

License

This article, along with any associated source code and files, is licensed under The zlib/libpng License

About the Author

Julijan Sribar
Software Developer (Senior) Syntellect
Croatia Croatia
Graduated at the Faculty of Electrical Engineering and Computing, University of Zagreb (Croatia) and received M.Sc. degree in electronics. For several years he was research and lecturing assistant in the fields of solid state electronics and electronic circuits, published several scientific and professional papers, as well as a book "Physics of Semiconductor Devices - Solved Problems with Theory" (in Croatian).
During that work he gained interest in C++ programming language and have co-written "C++ Demystified" (in Croatian), 1st edition published in 1997, 2nd in 2001, 3rd in 2010.
After book publication, completely switched to software development, programming mostly in C++ and in C#.

Comments and Discussions

 
GeneralFlatStyle PinmemberDan Hulse11-Feb-05 1:44 
GeneralRe: FlatStyle PinmemberJulijan Sribar12-Feb-05 11:33 
GeneralGood Pinmembersreejith ss nair24-Nov-04 16:12 
GeneralVery Nice! PinmemberJoshua Quick12-Nov-04 8:42 
GeneralRe: Very Nice! PinmemberJulijan Sribar12-Nov-04 9:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140415.2 | Last Updated 15 Nov 2004
Article Copyright 2004 by Julijan Sribar
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid