Discussion:
How to change colour of TextBox border
(too old to reply)
Notre Poubelle
2007-07-01 23:00:02 UTC
Permalink
Hello,

I'm trying to figure out how to change the border colour of the TextBox
control. I can't find a property that does this. I've researched this but
couldn't find a complete sample of anyone achieving this.

For the Textbox control, the overriden OnPaint method is not called unless
the control takes full responsibility for drawing the Textbox control but
that's not something I want to do; I just want to change the border colour.
A suggestion I found was to override the WM_PAINT message in WndProc. I did
this, and could use the Graphics.FromHwnd method to get access to GDI. I
could then draw a rectangle, but it was only in the interior of the TextBox,
not the outside so it was clipping the user entered text.

I think I need to draw to the non-client area (is that right?) of the
TextBox control. I handled the WM_NCPAINT message in WndProc and then
borrowed & adapted a routine I found on the web that looks like this (after
the WndProc):

protected override void WndProc(ref Message m)
{
if (m.Msg == 0x85) //WM_NCPAINT
{
PaintNonClientArea(m.HWnd, (IntPtr)m.WParam);
return;
}
base.WndProc(ref m);
}


private void PaintNonClientArea(IntPtr hWnd, IntPtr hRgn)
{
RECT windowRect = new RECT();
if (NativeMethods.GetWindowRect(hWnd, out windowRect) == false)
return;

Rectangle bounds = new Rectangle(0, 0,
windowRect.Right - windowRect.Left,
windowRect.Bottom - windowRect.Top);

if (bounds.Width == 0 || bounds.Height == 0)
return;

Region clipRegion = null;
if (hRgn != (IntPtr)1)
clipRegion = System.Drawing.Region.FromHrgn(hRgn);

IntPtr hDC = NativeMethods.GetDCEx(hWnd, hRgn,
(DeviceContextValues.Window | DeviceContextValues.IntersectRgn
| DeviceContextValues.Cache |
DeviceContextValues.ClipChildren));



if (hDC == IntPtr.Zero)
throw new
System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());

using (Graphics g = Graphics.FromHdc(hDC))
{
using (Pen pen = new Pen(Brushes.Green))
{
Rectangle myRect2 = new Rectangle();
myRect2.X = 0;
myRect2.Y = 0;
myRect2.Width = bounds.Width - 1;
myRect2.Height = bounds.Height - 1;
g.DrawRectangle(pen, myRect2);
}
}

}

The problem is that the call to GetDCEx always returns 0, and the Win32
exception thrown says invalid 'The parameter is incorrect'. The second
argument hdC seems to be what's causing the problem. This usually evaluates
to 1 (from the WM_NCPAINT message) but when it gets passed into GetDCEx, I
get the failure. Any idea what I'm doing wrong?

Thanks,
Notre
Kevin S Gallagher
2007-07-17 18:10:22 UTC
Permalink
Found this but in VB not C#
http://www.vb-tips.com/dbpages.aspx?ID=7c2b951c-4f39-4a8b-87f0-58fd21b7e2ea
Post by Notre Poubelle
Hello,
I'm trying to figure out how to change the border colour of the TextBox
control. I can't find a property that does this. I've researched this but
couldn't find a complete sample of anyone achieving this.
For the Textbox control, the overriden OnPaint method is not called unless
the control takes full responsibility for drawing the Textbox control but
that's not something I want to do; I just want to change the border colour.
A suggestion I found was to override the WM_PAINT message in WndProc. I did
this, and could use the Graphics.FromHwnd method to get access to GDI. I
could then draw a rectangle, but it was only in the interior of the TextBox,
not the outside so it was clipping the user entered text.
I think I need to draw to the non-client area (is that right?) of the
TextBox control. I handled the WM_NCPAINT message in WndProc and then
borrowed & adapted a routine I found on the web that looks like this (after
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x85) //WM_NCPAINT
{
PaintNonClientArea(m.HWnd, (IntPtr)m.WParam);
return;
}
base.WndProc(ref m);
}
private void PaintNonClientArea(IntPtr hWnd, IntPtr hRgn)
{
RECT windowRect = new RECT();
if (NativeMethods.GetWindowRect(hWnd, out windowRect) == false)
return;
Rectangle bounds = new Rectangle(0, 0,
windowRect.Right - windowRect.Left,
windowRect.Bottom - windowRect.Top);
if (bounds.Width == 0 || bounds.Height == 0)
return;
Region clipRegion = null;
if (hRgn != (IntPtr)1)
clipRegion = System.Drawing.Region.FromHrgn(hRgn);
IntPtr hDC = NativeMethods.GetDCEx(hWnd, hRgn,
(DeviceContextValues.Window |
DeviceContextValues.IntersectRgn
| DeviceContextValues.Cache |
DeviceContextValues.ClipChildren));
if (hDC == IntPtr.Zero)
throw new
System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
using (Graphics g = Graphics.FromHdc(hDC))
{
using (Pen pen = new Pen(Brushes.Green))
{
Rectangle myRect2 = new Rectangle();
myRect2.X = 0;
myRect2.Y = 0;
myRect2.Width = bounds.Width - 1;
myRect2.Height = bounds.Height - 1;
g.DrawRectangle(pen, myRect2);
}
}
}
The problem is that the call to GetDCEx always returns 0, and the Win32
exception thrown says invalid 'The parameter is incorrect'. The second
argument hdC seems to be what's causing the problem. This usually evaluates
to 1 (from the WM_NCPAINT message) but when it gets passed into GetDCEx, I
get the failure. Any idea what I'm doing wrong?
Thanks,
Notre
Notre Poubelle
2007-07-17 19:20:01 UTC
Permalink
Thanks Kevin! That sample does work really well (it was easy enough to
convert to C#). I really want to create my own inherited textboxes, but if
all else fails this might be an acceptable workaround.

Notre
unknown
2010-04-23 12:43:44 UTC
Permalink
If you're still interested, I wrote a quick hack for this:

http://nathetnico.fr/dev/archives/115




notre_poubell wrote:

Thanks Kevin!
17-Jul-07

Thanks Kevin! That sample does work really well (it was easy enough to
convert to C#). I really want to create my own inherited textboxes, but if
all else fails this might be an acceptable workaround

Notre

Previous Posts In This Thread:

On Sunday, July 01, 2007 7:00 PM
notre_poubell wrote:

How to change colour of TextBox border
Hello

I'm trying to figure out how to change the border colour of the TextBox
control. I can't find a property that does this. I've researched this but
couldn't find a complete sample of anyone achieving this.

For the Textbox control, the overriden OnPaint method is not called unless
the control takes full responsibility for drawing the Textbox control but
that's not something I want to do; I just want to change the border colour.
A suggestion I found was to override the WM_PAINT message in WndProc. I did
this, and could use the Graphics.FromHwnd method to get access to GDI. I
could then draw a rectangle, but it was only in the interior of the TextBox,
not the outside so it was clipping the user entered text

I think I need to draw to the non-client area (is that right?) of the
TextBox control. I handled the WM_NCPAINT message in WndProc and then
borrowed & adapted a routine I found on the web that looks like this (after
the WndProc)

protected override void WndProc(ref Message m

if (m.Msg == 0x85) //WM_NCPAIN

PaintNonClientArea(m.HWnd, (IntPtr)m.WParam)
return

base.WndProc(ref m)


private void PaintNonClientArea(IntPtr hWnd, IntPtr hRgn

RECT windowRect = new RECT()
if (NativeMethods.GetWindowRect(hWnd, out windowRect) == false
return

Rectangle bounds = new Rectangle(0, 0
windowRect.Right - windowRect.Left
windowRect.Bottom - windowRect.Top)

if (bounds.Width == 0 || bounds.Height == 0
return

Region clipRegion = null
if (hRgn != (IntPtr)1
clipRegion = System.Drawing.Region.FromHrgn(hRgn)

IntPtr hDC = NativeMethods.GetDCEx(hWnd, hRgn
(DeviceContextValues.Window | DeviceContextValues.IntersectRg
| DeviceContextValues.Cache |
DeviceContextValues.ClipChildren))


if (hDC == IntPtr.Zero
throw new
System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error())

using (Graphics g = Graphics.FromHdc(hDC)

using (Pen pen = new Pen(Brushes.Green)

Rectangle myRect2 = new Rectangle()
myRect2.X = 0
myRect2.Y = 0
myRect2.Width = bounds.Width - 1
myRect2.Height = bounds.Height - 1
g.DrawRectangle(pen, myRect2)





The problem is that the call to GetDCEx always returns 0, and the Win32
exception thrown says invalid 'The parameter is incorrect'. The second
argument hdC seems to be what's causing the problem. This usually evaluates
to 1 (from the WM_NCPAINT message) but when it gets passed into GetDCEx, I
get the failure. Any idea what I'm doing wrong

Thanks
Notre

On Tuesday, July 17, 2007 2:10 PM
Kevin S Gallagher wrote:

Re: How to change colour of TextBox border
Found this but in VB not C
http://www.vb-tips.com/dbpages.aspx?ID=7c2b951c-4f39-4a8b-87f0-58fd21b7e2ea

On Tuesday, July 17, 2007 3:20 PM
notre_poubell wrote:

Thanks Kevin!
Thanks Kevin! That sample does work really well (it was easy enough to
convert to C#). I really want to create my own inherited textboxes, but if
all else fails this might be an acceptable workaround

Notre


Submitted via EggHeadCafe - Software Developer Portal of Choice
Book Review: C# 4.0 In a Nutshell [O'Reilly]
http://www.eggheadcafe.com/tutorials/aspnet/6dc05c04-c7f9-40cc-a2da-88dde2e6d891/book-review-c-40-in-a.aspx
Loading...