The standard Windows Forms TextBox gives you very little control over its border. You can switch between Fixed3D, FixedSingle, and None, but you cannot change the border colour or choose which sides to draw. If your application uses a custom colour scheme or a design that calls for a bottom-border-only input field, the built-in options fall short.
TheUserControlbelow wraps a borderlessTextBoxinside a painted container and draws the border itself usingControlPaint.DrawBorder, giving you full control over colour, thickness, and which sides are visible.
The custom TextBox control
The control hosts a TextBox with BorderStyle.None and paints the border on the UserControl surface instead. The SetBorderSide property selects which sides to draw, and TextBoxBorderColor sets the colour. Both are available in the designer as well as in code.
public partial class TextBoxTemplate : UserControl
{
TextBox textBox1 = new TextBox();
private Color BorderColor;
private HorizontalAlignment TextAlign;
public enum BorderSides { Left, Right, Top, Bottom, All }
public BorderSides SetBorderSide = BorderSides.All;
int BorderSize = 1;
public TextBoxTemplate()
{
InitializeComponent();
textBox1.Multiline = true;
textBox1.BorderStyle = BorderStyle.None;
textBox1.Font = this.Font;
textBox1.BackColor = this.BackColor;
textBox1.TextAlign = HorizontalAlignment.Center;
this.Controls.Add(textBox1);
}
public override string Text
{
get { return textBox1.Text; }
set { textBox1.Text = value; }
}
public Color TextBoxBorderColor
{
get { return this.BorderColor; }
set { this.BorderColor = value; }
}
public HorizontalAlignment TextBoxAlign
{
get { return this.TextAlign; }
set { this.TextAlign = value; }
}
private void TextBoxTemplate_Paint(object sender, PaintEventArgs e)
{
Rectangle txtRect = this.ClientRectangle;
switch (SetBorderSide)
{
case BorderSides.All:
ControlPaint.DrawBorder(e.Graphics, this.ClientRectangle,
BorderColor, BorderSize, ButtonBorderStyle.Solid,
BorderColor, BorderSize, ButtonBorderStyle.Solid,
BorderColor, BorderSize, ButtonBorderStyle.Solid,
BorderColor, BorderSize, ButtonBorderStyle.Solid);
break;
case BorderSides.Left:
ControlPaint.DrawBorder(e.Graphics, txtRect,
BorderColor, BorderSize, ButtonBorderStyle.Solid,
BorderColor, 0, ButtonBorderStyle.Solid,
BorderColor, 0, ButtonBorderStyle.Solid,
BorderColor, 0, ButtonBorderStyle.Solid);
break;
case BorderSides.Top:
ControlPaint.DrawBorder(e.Graphics, txtRect,
BorderColor, 0, ButtonBorderStyle.Solid,
BorderColor, BorderSize, ButtonBorderStyle.Solid,
BorderColor, 0, ButtonBorderStyle.Solid,
BorderColor, 0, ButtonBorderStyle.Solid);
break;
case BorderSides.Right:
ControlPaint.DrawBorder(e.Graphics, txtRect,
BorderColor, 0, ButtonBorderStyle.Solid,
BorderColor, 0, ButtonBorderStyle.Solid,
BorderColor, BorderSize, ButtonBorderStyle.Solid,
BorderColor, 0, ButtonBorderStyle.Solid);
break;
case BorderSides.Bottom:
ControlPaint.DrawBorder(e.Graphics, txtRect,
BorderColor, 0, ButtonBorderStyle.Solid,
BorderColor, 0, ButtonBorderStyle.Solid,
BorderColor, 0, ButtonBorderStyle.Solid,
BorderColor, BorderSize, ButtonBorderStyle.Solid);
break;
default:
break;
}
textBox1.BackColor = this.BackColor;
}
private void TextBoxTemplate_SizeChanged(object sender, EventArgs e)
{
textBox1.Size = new Size(this.Width - 3, this.Height - 2);
textBox1.Location = new Point(2, 1);
textBox1.Font = this.Font;
textBox1.BackColor = this.BackColor;
}
}
How it works
A few details worth understanding before dropping this into a project:
- Borderless inner TextBox: Setting
BorderStyle.Noneon the innerTextBoxremoves the system-drawn border entirely. TheUserControlsurface becomes the visible boundary, which is where the custom border is painted. - ControlPaint.DrawBorder: This method accepts four sets of arguments in left, top, right, bottom order. Each set is a colour, a width, and a style. Setting the width to
0for a side suppresses that side's border, which is how the individualBorderSidescases work. - SizeChanged handler: The inner
TextBoxis sized to leave a small inset (2 pixels left, 1 pixel top) so the painted border on theUserControlis never obscured by the text area. Font and background colour are kept in sync with the parent on every resize.
Tip: To make
SetBorderSide and TextBoxBorderColor editable in the Visual Studio designer, add a [Category("Appearance")] attribute above each public property. Without it the properties appear under the Misc category, which is easy to overlook.
When to use this
- Applications with a custom colour scheme where the default grey system border does not match the design.
- Modern-looking forms that use a bottom-border-only input style, similar to Material Design text fields.
- Any project where consistent branded input controls need to be reused across multiple forms without repeating owner-draw logic in each one.
Found this useful? Drop a comment below if you have a variation or ran into an edge case I did not cover.
No comments: