views:

695

answers:

2

In C# I have custom form of None border style which override onPaint event and draw custom background with transparency key. I want to set my own client rectangle value (so content would be placed inside my custom border), but unfortunally Form's ClientRectangle property is read-only. I found advice over net to override WndProc method (where it sets client size) but saddly, I found very little info about that. Especially it requires to fill data which are pointed by lParam and wParam and I really don't know how to do this in C#.

Any help?

A: 

As you are responsible for painting the entire form, it is probably simplest to define your own content Rectangle that is positioned ,say, 10 pixels in from the top/left of the form and has a width/height 20 pixels less then the form width/height.

Then, in the control Paint event, first draw your border area as normal, then call Graphics.Translate(10,10) and then draw the actual content.

Ash
+2  A: 

Your question has a couple of things that concern me... first you want draw your own border and then adjust the client rectangle. This really isn't possible as the client rectangle is determined when the window moves. Once determined a completely different paint message is responsible for drawing all non-client content. Thus you can do what you suggest; however, it will break your current border painting.

It would be FAR eaiser to move all your controls from your form into a new Panel control and place it on the form. Now you can position this panel as if you where adjusting the client area.

If you must proceed with your original thought to modify the window client area you would do the following:

    private void AdjustClientRect(ref RECT rcClient)
    {
        rcClient.Left += 10;
        rcClient.Top += 10;
        rcClient.Right -= 10;
        rcClient.Bottom -= 10;
    }

    struct RECT { public int Left, Top, Right, Bottom; }
    struct NCCALCSIZE_PARAMS
    {
        public RECT rcNewWindow;
        public RECT rcOldWindow;
        public RECT rcClient;
        IntPtr lppos;
    }

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);

        const int WM_NCCALCSIZE = 0x0083;
        if (m.Msg == WM_NCCALCSIZE)
        {
            if (m.WParam != IntPtr.Zero)
            {
                NCCALCSIZE_PARAMS rcsize = (NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(NCCALCSIZE_PARAMS));
                AdjustClientRect(ref rcsize.rcNewWindow);
                Marshal.StructureToPtr(rcsize, m.LParam, false);
            }
            else
            {
                RECT rcsize = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT));
                AdjustClientRect(ref rcsize);
                Marshal.StructureToPtr(rcsize, m.LParam, false);
            }
            m.Result = new IntPtr(1);
            return;
        }
    }
csharptest.net
I though about creating simple docked panel with BackColor = Color.Transparent and padding of parent form setting new client size. Parrent control also override own Controls property of parent form to get panel's Controls. But this doesn't work for one reason: it is too slow if Control display image and is rescaled
PiotrK