protected override
void WndProc(ref
Message m)
{
//calculate
the maximum size of the non-client border area
//3
is the minimum because the border is 3 pizels wide
int
bmax=(int)Math.Max(3,_borderRadius);
//0.41
is a fudge factor. A square of approximately 0.82*diameter will fit neatly into
a circle
//with
diameter of 1 so 0.41 is half of the diameter
int
adustedbmax=(int)Math.Max(3,0.40*bmax);
switch(m.Msg)
{
case
(int)WmDefs.WM_NCCALCSIZE:
if
((int)m.WParam == 0)
{
//Shrink
the window rect to create the client rect
RECT
rc=(RECT)Marshal.PtrToStructure(m.LParam,typeof(RECT));
rc.left+=adustedbmax;
rc.top+=adustedbmax
;
rc.right-=adustedbmax
;
rc.bottom-=adustedbmax
;
Marshal.StructureToPtr(rc,m.LParam,false);
m.Result=IntPtr.Zero;
}
break;
case
(int)WmDefs.WM_NCPAINT:
{
//get
the window DC
IntPtr dc=GetWindowDC(m.HWnd);
//and
the window rectangle in screen coordinates
RECT rc=new RECT();
GetWindowRect(m.HWnd,ref rc);
//convert
to a GDI+ rectangle and translate to client coordinates
Rectangle r=new
Rectangle(rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top);
r=this.RectangleToClient(r);
//because
the rectangle origin is negative with respect to the client area
//we
offset the rectangle so that it fits into the WindowDC correctly
r.Offset(adustedbmax,adustedbmax);
//Create
a rectangle that is the right size for the border. 3 pixels smalller than the
window DC
Rectangle rcBorder=r;
rcBorder.Width-=3;
rcBorder.Height-=3;
//Get
a graphics for the WindowDC
Graphics g=Graphics.FromHdc(dc);
//the
client rectangle and the window rectangle are used to make a region
//that
includes the border but excludes the client area to reduce potential flicker
Rectangle r2=this.ClientRectangle;
r2.Offset(adustedbmax,adustedbmax);
Region rg=new Region(r);
rg.Exclude(r2);
//the
clipping region is set to include only the non-client area
g.SetClip(rg,CombineMode.Replace);
g.Clear(BackColor);
//Now
a 3 pixel 3D shaded border is drawn using
//3
overlapping round-rectangles
Pen
p=new Pen(Color.White,1);
g.SmoothingMode=SmoothingMode.AntiAlias;
//#1
RoundRect(g,
p, rcBorder, bmax);
p.Color=Color.Gray;
rcBorder.Offset(2,2);
//#2
RoundRect(g,
p, rcBorder, bmax);
p.Color=Color.Black;
rcBorder.Offset(-1,-1);
//#3
RoundRect(g,
p, rcBorder, bmax);
//clean
up.
p.Dispose();
g.Dispose();
ReleaseDC(m.HWnd,dc);
//signal
success
m.Result=IntPtr.Zero;
}
break;
default:
base.WndProc(ref
m);
break;
}
}
Protected Overrides
Sub WndProc(ByRef
m As Message)
'calculate
the maximum size of the non-client border area
'3
is the minimum because the border is 3 pizels wide
Dim
bmax As Integer
= CInt(Math.Max(3, _borderRadius))
'0.41
is a fudge factor. A square of approximately 0.82*diameter will fit neatly into
a circle
'with
diameter of 1 so 0.41 is half of the diameter
Dim
adustedbmax As Integer
= CInt(Math.Max(3, 0.4 * bmax))
Select
Case m.Msg
Case
CInt(WmDefs.WM_NCCALCSIZE)
If
m.WParam.ToString() = "0" Then
'Visual Basic is a truly ridiculous language!
'Shrink
the window rect to create the client rect
Dim
rc As RECT = CType(Marshal.PtrToStructure(m.LParam,
GetType(RECT)), RECT)
rc.left
+= adustedbmax
rc.top
+= adustedbmax
rc.right
-= adustedbmax
rc.bottom
-= adustedbmax
Marshal.StructureToPtr(rc,
m.LParam, False)
m.Result
= IntPtr.Zero
End
If
Case
CInt(WmDefs.WM_NCPAINT)
If
(True) Then
'get
the window DC
Dim
dc As IntPtr = GetWindowDC(m.HWnd)
'and
the window rectangle in screen coordinates
Dim
rc As New RECT
GetWindowRect(m.HWnd,
rc)
'convert
to a GDI+ rectangle and translate to client coordinates
Dim
r As New
Rectangle(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top)
r
= Me.RectangleToClient(r)
'because
the rectangle origin is negative with respect to the client area
'we
offset the rectangle so that it fits into the WindowDC correctly
r.Offset(adustedbmax,
adustedbmax)
'Create
a rectangle that is the right size for the border. 3 pixels smalller than the
window DC
Dim
rcBorder As Rectangle = r
rcBorder.Width
-= 3
rcBorder.Height
-= 3
'Get
a graphics for the WindowDC
Dim
g As Graphics = Graphics.FromHdc(dc)
'the
client rectangle and the window rectangle are used to make a region
'that
includes the border but excludes the client area to reduce potential flicker
Dim
r2 As Rectangle = Me.ClientRectangle
r2.Offset(adustedbmax, adustedbmax)
Dim
rg As New
[Region](r)
rg.Exclude(r2)
'the
clipping region is set to include only the non-client area
g.SetClip(rg, CombineMode.Replace)
g.Clear(BackColor)
'Now
a 3 pixel 3D shaded border is drawn using
'3
overlapping round-rectangles
Dim
p As New
Pen(Color.White, 1)
g.SmoothingMode
= SmoothingMode.AntiAlias
'#1
RoundRect(g,
p, rcBorder, bmax)
p.Color
= Color.Gray
rcBorder.Offset(2, 2)
'#2
RoundRect(g,
p, rcBorder, bmax)
p.Color
= Color.Black
rcBorder.Offset(-1,
-1)
'#3
RoundRect(g,
p, rcBorder, bmax)
'clean
up.
p.Dispose()
g.Dispose()
ReleaseDC(m.HWnd,
dc)
'signal
success
m.Result
= IntPtr.Zero
End
If
Case
Else
MyBase.WndProc(m)
End
Select
End
Sub 'WndProc