I've been messing around with this Paint method for hours now. This is the cleanest/closest solution I could come up with. I even tried making a custom TextBox Control instead, but I think that's out of my current skill set. FYI I am new to VS and C#, so take it easy on me please.
//Draw Borders around our Controls
private void Form1_Paint(object sender, PaintEventArgs e)
{
//Loops through all our text boxes and draws a border
//Works fine when the textbox is just in the form.
foreach (TextBox txt in this.Controls.OfType<TextBox>())
{
Rectangle rect = new Rectangle(txt.Location.X, txt.Location.Y, txt.ClientSize.Width, txt.ClientSize.Height);
rect.Inflate(1, 1);
ControlPaint.DrawBorder(e.Graphics, rect, Color.FromArgb(255, 0, 0), ButtonBorderStyle.Solid);
}
//Loops through all Panels and draws a border
foreach (Panel pnl in this.Controls.OfType<Panel>())
{
Rectangle rect = new Rectangle(pnl.Location.X, pnl.Location.Y, pnl.ClientSize.Width, pnl.ClientSize.Height);
rect.Inflate(1, 1);
ControlPaint.DrawBorder(e.Graphics, rect, Color.FromArgb(0, 0, 0), ButtonBorderStyle.Solid);
//Loops through all our TextBoxes in the Panels and draws a border
//Not drawing the border around the textbox
foreach (TextBox txt in pnl.Controls.OfType<TextBox>())
{
rect = new Rectangle(txt.Location.X, txt.Location.Y, txt.ClientSize.Width, txt.ClientSize.Height);
rect.Inflate(1, 1);
ControlPaint.DrawBorder(e.Graphics, rect, Color.FromArgb(255, 0, 0), ButtonBorderStyle.Solid);
txt.Text = "FML"; //Just added this to see if we were interacting with each TextBox, and we are.
}
}
//To simplify the nested loop above I tried to just draw a border directly to textBox2, which is inside a Panel.
Rectangle rect2 = new Rectangle(textBox2.Location.X, textBox2.Location.Y, textBox2.ClientSize.Width, textBox2.ClientSize.Height);
rect2.Inflate(1, 1);
ControlPaint.DrawBorder(e.Graphics, rect2, Color.FromArgb(255, 0, 0), ButtonBorderStyle.Solid);
textBox2.Text = "Hello World"; //Still changing the text, just no border.
}
You can't see the drawing because your coordinates are off because you mix two things:
Form.Paint
event, but.. Textboxes
' Locations
, which are relative to the Panel
they sit in. You can either
Panel.Paint
event or.. TextBox
locations to be relative to the Form
. For the latter solution you can use the Rectangle.Offset(Point)
function. Do take the border styles into account; also note that ClientSize
is the area inside the borders only..
The first solution also assumes the Panel
is transparent and that no other controls are between Panel
and Form
!
This works for me:
rect = new Rectangle(textBox3.Left - 1, textBox3.Top - 1,
textBox3.Width + 1, textBox3.Height + 1);
rect.Offset(panel1.Location);
Also note that Rectangle.Inflate(a,b)
will not just increase Width
by a
but by a*2
and also decrease Left
by a
etc.
Final note: Do note that there is a difference of how DrawRectangle and FillRectangle treat the size to draw or fill!
https://github.com/vignesh-nethaji/Windows-Custom-Controls/blob/master/Menporul.Windows/Menporul.Windows.Controls/Controls/MenTextBox.cs
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace Menporul.Windows.Controls
{
/// <summary>
/// Menporul TextBox
/// </summary>
/// <author>Vignesh Nethaji</author>
public class MenTextBox : TextBox
{
/// <summary>
/// Border Color when textbox focus
/// </summary>
private Color _focusBorderColor = Color.Blue;
/// <summary>
/// Default Border Color
/// </summary>
private Color _defaultBorderColor = Color.Gray;
/// <summary>
///
/// </summary>
public MenTextBox()
{
}
/// <summary>
/// On control resize refresh the control for Border rendering based on the control size
/// </summary>
/// <param name="e"></param>
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
this.Refresh();
}
/// <summary>
/// Getting device context for creating graphics for draw border on textbox
/// </summary>
/// <param name="hwnd"></param>
/// <returns></returns>
[DllImport("user32")]
private static extern IntPtr GetWindowDC(IntPtr hwnd);
/// <summary>
/// Draw textbox border when its painting
/// </summary>
/// <param name="m"></param>
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0x85 || m.Msg == 0x000F)
{
Rectangle rect = new Rectangle(0, 0, Width, Height);
if (this.Focused)
{
var dc = GetWindowDC(Handle);
using (Graphics g = Graphics.FromHdc(dc))
{
ControlPaint.DrawBorder(g, rect,
_focusBorderColor, 2, ButtonBorderStyle.Solid,
_focusBorderColor, 2, ButtonBorderStyle.Solid,
_focusBorderColor, 2, ButtonBorderStyle.Solid,
_focusBorderColor, 2, ButtonBorderStyle.Solid);
}
}
else
{
var dc = GetWindowDC(Handle);
using (Graphics g = Graphics.FromHdc(dc))
{
ControlPaint.DrawBorder(g, rect,
_defaultBorderColor, 1, ButtonBorderStyle.Solid,
_defaultBorderColor, 1, ButtonBorderStyle.Solid,
_defaultBorderColor, 1, ButtonBorderStyle.Solid,
_defaultBorderColor, 1, ButtonBorderStyle.Solid);
}
}
}
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.