In this post, I’ll show you how you can customize the panel border size and border color by customizing the nonclient area of the panel.
The following picture shows panels with different border color and border size:
When you set BorderStyle of a standard panel control to FixedSingle, you see a black 1-pixel border around the panel. This black border is nonclient area for the panel:
- It’s not on the client rectangle, which means none of the controls of the form can cover the border
- You cannot paint on that area in
OnPaint
method orPaint
event - You cannot change it’s width using common properties of the panel.
To modify the size and appearance of the nonclient area, you need to override the WndProc
and handle some windows messages. Here we are especially interested in the following messages:
WM_NCCALCSIZE
: To change the size of the nonclient areaWM_NCPAINT
: To paint on the nonclient area.
You also need to make sure when the control size changes, or when you modify the border width of the control, or when you mofidy the border color, the correct client and nonclient area will be calculated correctlty and both areas will be repainted.
Change the size of nonclien area
To change the size and appearance of the border, you first need to handle WM_NCCALCSIZE
message get an instance of NCCALCSIZE_PARAMS
structure from the lparam of the message. The rgrc
member of the strcuture is an array of
RECT
structure. The first rectangle containse the bounds of the rectanle; then if you modify it and return zero as the result of the message, the default window procedure will use this rect as the client rectange of the control and difference between original value and the new value will be used as nonclient area:
if (m.WParam != IntPtr.Zero)
{
var nccsp = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
nccsp.rgrc[0].top += borderWidth - 1;
nccsp.rgrc[0].bottom -= borderWidth - 1;
nccsp.rgrc[0].left += borderWidth - 1;
nccsp.rgrc[0].right -= borderWidth - 1;
Marshal.StructureToPtr(nccsp, m.LParam, true);
InvalidateRect(this.Handle, nccsp.rgrc[0], true);
m.Result = IntPtr.Zero;
}
Change appearance of the nonclient area
To change the appearance of nonclient area you need to handle WM_NCPAINT
. Then you can get the device context handler using GetWindowDC
and pass it to Graphics.FromHdc
to get graphics object and paint on non-clien area:
var dc = GetWindowDC(Handle);
using (var g = Graphics.FromHdc(dc))
{
using (var p = new Pen(BorderColor, borderWidth) { Alignment = PenAlignment.Inset })
{
if (VScroll && HScroll)
{
Rectangle bottomCornerRectangle = new Rectangle(
Width - SystemInformation.VerticalScrollBarWidth - borderWidth,
Height - SystemInformation.HorizontalScrollBarHeight - borderWidth,
SystemInformation.VerticalScrollBarWidth,
SystemInformation.HorizontalScrollBarHeight);
if (RightToLeft == RightToLeft.Yes)
{
bottomCornerRectangle.X = Width - bottomCornerRectangle.Right;
}
g.FillRectangle(SystemBrushes.Control, bottomCornerRectangle);
}
var adjustment = borderWidth == 1 ? 1 : 0;
g.DrawRectangle(p, 0, 0, Width - adjustment, Height - adjustment);
}
}
ReleaseDC(Handle, dc);
Invalidate the size and appearance of nonclient area
If you want to have a BorderWidth
property, it should change the size of the nonclient area without resizing the control. To do this, you can call
SetWindowPos
by setting the SWP_FRAMECHANGED
flag.
SetWindowPos(this.Handle, IntPtr.Zero, 0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED | SWP_NOZOORDER);
If you want to have a BorderColor
property, when you change it, it should repaint the nonclient area; however non of the Refresh, Invalidate, or Update method repaints nonclient area. To push repainting of the nonclient area, you need to RedrawWindow
by setting the SWP_FRAMECHANGED
flag.
RedrawWindow(Handle, IntPtr.Zero, IntPtr.Zero,
RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW);
Download
You can clone or download the code:
سلام جناب رضا آقایی . من ممکنه سوالی در مورد vb.net از شما بپرسم.
اگه اجازه بدین که ممنون میشم.
و اینکه چطور میتونم به شما پیامم رو ارسال کنم.
من اهل مشهد هستم . من تو یه قسمت از برنامه نویسیم گیر کردم. خیلی ممنون میشم که مقداری از معلومات خودتون رو در اختیار بزارین.