.
In Depth Banner
Skip Navigation Links

Select your preferred language

The custom windows procedure. 

    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;

      }

    }

 

Return to the article. 

Copyright © Bob Powell 2000-.  All rights reserved.