I've been trying to paint custom borders for existing .Net WinForms controls. I've attempted this by creating a class which from the control I want to change the border color of, and then try several things during painting. I've tried the following:
1. Catch WM_NCPAINT
. This works, somewhat. The problem with the code below is that when the control resizes, the border will be cut off on the right and bottom side. Not good.
protected override void WndProc(ref Message m)
{
if (m.Msg == NativeMethods.WM_NCPAINT) {
WmNcPaint(ref m);
return;
}
base.WndProc(ref m);
}
private void WmNcPaint(ref Message m)
{
if (BorderStyle == BorderStyle.None) {
return;
}
IntPtr hDC = NativeMethods.GetWindowDC(m.HWnd);
if (hDC != IntPtr.Zero) {
using (Graphics g = Graphics.FromHdc(hDC)) {
ControlPaint.DrawBorder(g, new Rectangle(0, 0, this.Width, this.Height), _BorderColor, ButtonBorderStyle.Solid);
}
m.Result = (IntPtr)1;
NativeMethods.ReleaseDC(m.HWnd, hDC);
}
}
2. Override void OnPaint
. This works for some controls, but not all. This also requires that you set BorderStyle
to BorderStyle.None
, and you have to manually clear the background on paint, otherwise you get this when you resize.
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
ControlPaint.DrawBorder(e.Graphics, new Rectangle(0, 0, this.Width, this.Height), _BorderColor, ButtonBorderStyle.Solid);
}
3. Overriding void OnResize
and void OnPaint
(like in method 2). This way, it paints well with resizing, but not when the Panel has AutoScroll
enabled, in which case it will look like this when scrolling down. If I try to use WM_NCPAINT
to paint the border, Refresh()
has no effect.
protected override void OnResize(EventArgs eventargs)
{
base.OnResize(eventargs);
Refresh();
}
Suggestions are more than welcome. I'd like to know what the best way to go about this is, for multiple types of controls (I'll have to do this for multiple default WinForms controls).