Change border color in TextBox C#
To change border color of TextBox
you can override WndProc
method and handle WM_NCPAINT
message. Then get the window device context of the control using GetWindowDC
because we want to draw to non-client area of control. Then to draw, it's enough to create a Graphics
object from that context, then draw border for control.
To redraw the control when the BorderColor
property changes, you can use RedrawWindow
method.
Code
Here is a TextBox
which has a BorderColor
property. The control uses BorderColor
if the property values is different than Color.Transparent
and BorderStyle
is its default value Fixed3d
.
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class MyTextBox : TextBox {
const int WM_NCPAINT = 0x85;
const uint RDW_INVALIDATE = 0x1;
const uint RDW_IUPDATENOW = 0x100;
const uint RDW_FRAME = 0x400;
[DllImport("user32.dll")]
static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("user32.dll")]
static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("user32.dll")]
static extern bool RedrawWindow(IntPtr hWnd, IntPtr lprc, IntPtr hrgn, uint flags);
Color borderColor = Color.Blue;
public Color BorderColor {
get { return borderColor; }
set { borderColor = value;
RedrawWindow(Handle, IntPtr.Zero, IntPtr.Zero,
RDW_FRAME | RDW_IUPDATENOW | RDW_INVALIDATE);
}
}
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
if (m.Msg == WM_NCPAINT && BorderColor != Color.Transparent &&
BorderStyle == System.Windows.Forms.BorderStyle.Fixed3D) {
var hdc = GetWindowDC(this.Handle);
using (var g = Graphics.FromHdcInternal(hdc))
using (var p = new Pen(BorderColor))
g.DrawRectangle(p, new Rectangle(0, 0, Width - 1, Height - 1));
ReleaseDC(this.Handle, hdc);
}
}
protected override void OnSizeChanged(EventArgs e) {
base.OnSizeChanged(e);
RedrawWindow(Handle, IntPtr.Zero, IntPtr.Zero,
RDW_FRAME | RDW_IUPDATENOW | RDW_INVALIDATE);
}
}
Result
Here is the result using different colors and different states. All states of border-style is supported as you can see in below image and you can use any color for border:
Download
You can clone or download the working example:
- Download Zip
- Github repository
You have to draw text manually as well.
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Pen penBorder = new Pen(Color.Gray, 1);
Rectangle rectBorder = new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1);
e.Graphics.DrawRectangle(penBorder, rectBorder);
Rectangle textRec = new Rectangle(e.ClipRectangle.X + 1, e.ClipRectangle.Y + 1, e.ClipRectangle.Width - 1, e.ClipRectangle.Height - 1);
TextRenderer.DrawText(e.Graphics, Text, this.Font, textRec, this.ForeColor, this.BackColor, TextFormatFlags.Default);
}
Alternatively you can try to use e.Graphics.DrawString()
method if TextRenderer
is not giving you desired results (I always have better results with this approach thou).