Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Reducing the clientarea of a custom control

104 views
Skip to first unread message

Joey Callisay

unread,
Sep 13, 2004, 2:42:35 AM9/13/04
to
I have this usercontrol (container) which has a border on the inside. I
want to be able to limit the client area of the control inside this border
so controls dragged into it will not be outside this border? How can I
implement this restriction?

Thanks a lot!


lukasz

unread,
Sep 13, 2004, 5:20:08 AM9/13/04
to
You need to resort to WinAPI to accomplish it and process the WM_NC*
messages which are responsible for non-client area of your control.
Non-client area is handled differently from client area: you need to
separately process all messages for it, like drawing and click testing.

In WM_NCCALCSIZE you reduce initial rectangle to exclude your border.
In WM_NCPAINT you draw you border.
In WM_NCHITTEST you can assign certain Windows functionality to your border;
in my case it's just a border.
WM_NCMOUSEMOVE is same for nonclient area as WM_MOUSEMOVE (OnMouseMove) for
client area.
Similarly WM_NCLBUTTONDOWN, WM_NCLBUTTONUP, WM_NCRBUTTONDOWN, etc. -- they
stand for left button down, up, right button down, respectively, for
non-client area.

The point given by WM_NCMOUSEMOVE and WM_NC*BUTTON* is relative to client
area (first point of client area has coordinates (0, 0)) -- thus to get
absolute coordinates, where (0, 0) is in the upper-left corner of your
corner, on the non-client border , you need to offset the point by the width
of the left border and the height of the top border.

When you need to redraw your border (non-client area), you need to call a
special function because Invalidate(), Update() etc. won't do it. I named
the function "invalidateNC." You need to call it after your control's size
has changed (in OnSizeChanged()), too.

I'll show you some code of my control in C#, which has a header at the top
of height headerHeight and border around of width borderWidth:

using System.Runtime.InteropServices;


protected override void WndProc(ref Message m) {
Point pt;

switch ( m.Msg ) {
case (int)WinAPI_WM.WM_NCCALCSIZE :
if ( m.WParam == IntPtr.Zero ) {
WinAPI_NCCALCSIZE_PARAMS csp;

csp = (WinAPI_NCCALCSIZE_PARAMS)Marshal.PtrToStructure( m.LParam,
typeof(WinAPI_NCCALCSIZE_PARAMS));
csp.rgrc0.Top += headerHeight;
csp.rgrc0.Bottom -= borderWidth;
csp.rgrc0.Left += borderWidth;
csp.rgrc0.Right -= borderWidth;
Marshal.StructureToPtr( csp, m.LParam, false );

} else if (m.WParam == new IntPtr(1)) {
WinAPI_NCCALCSIZE_PARAMS csp;

csp = (WinAPI_NCCALCSIZE_PARAMS)Marshal.PtrToStructure( m.LParam,
typeof(WinAPI_NCCALCSIZE_PARAMS));
csp.rgrc0.Top += headerHeight;
csp.rgrc0.Bottom -= borderWidth;
csp.rgrc0.Left += borderWidth;
csp.rgrc0.Right -= borderWidth;
Marshal.StructureToPtr( csp, m.LParam, false );

}
break;

case (int)WinAPI_WM.WM_NCPAINT:

IntPtr hDC = GetWindowDC( m.HWnd );
Graphics g = Graphics.FromHdc( hDC );

// header
using (SolidBrush br = new SolidBrush(textBackColor)) {
g.FillRectangle(br, headerBounds);
}

// border
Rectangle rect = new Rectangle(0, 0, Width, Height);

using (Pen p = new Pen(borderColor, borderWidth)) {
p.Alignment = System.Drawing.Drawing2D.PenAlignment.Inset;
g.DrawRectangle(p, rect);
}


ReleaseDC( m.HWnd, hDC );

break;


case (int)WinAPI_WM.WM_NCHITTEST:
m.Result = (IntPtr)WinAPI_HT.HTBORDER;
return;


case (int)WinAPI_WM.WM_NCMOUSEMOVE:
pt = PointToClient( new Point( m.LParam.ToInt32() ) );
pt.Offset(borderWidth, headerHeight);
// ...

break;


case (int)WinAPI_WM.WM_NCLBUTTONDOWN:
pt = PointToClient( new Point( m.LParam.ToInt32() ) );
pt.Offset(borderWidth, headerHeight);
// ...

break;

}
base.WndProc (ref m);
}

/// <summary>
/// Invalidates non-client area
/// </summary>
private void invalidateNC() {

WinAPI.SetWindowPos(this.Handle, IntPtr.Zero, 0, 0, 0, 0,
WinAPI_SWP.SWP_NOMOVE |
WinAPI_SWP.SWP_NOSIZE |
WinAPI_SWP.SWP_NOZORDER |
WinAPI_SWP.SWP_NOACTIVATE |
WinAPI_SWP.SWP_DRAWFRAME
);
}

///////////// WINAPI functions/structures

[StructLayout(LayoutKind.Sequential)]
public struct WinAPI_NCCALCSIZE_PARAMS {
public WinAPI_RECT rgrc0, rgrc1, rgrc2;
public IntPtr lppos;
}

[DllImport("User32.dll")]
public extern static IntPtr GetWindowDC( IntPtr hWnd );

[DllImport("User32.dll")]
public extern static int ReleaseDC( IntPtr hWnd, IntPtr hDC );

[DllImport("user32.dll")]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr
hWndInsertAfter, int X,
int Y, int cx, int cy, uint uFlags);

public struct WinAPI_HT {
public const uint HTERROR = unchecked ((uint)-2);
public const uint HTTRANSPARENT = unchecked ((uint)-1);
public const int HTNOWHERE = 0;
public const int HTCLIENT = 1;
public const int HTCAPTION = 2;
public const int HTSYSMENU = 3;
public const int HTGROWBOX = 4;
public const int HTSIZE = HTGROWBOX;
public const int HTMENU = 5;
public const int HTHSCROLL = 6;
public const int HTVSCROLL = 7;
public const int HTMINBUTTON = 8;
public const int HTMAXBUTTON = 9;
public const int HTLEFT = 10;
public const int HTRIGHT = 11;
public const int HTTOP = 12;
public const int HTTOPLEFT = 13;
public const int HTTOPRIGHT = 14;
public const int HTBOTTOM = 15;
public const int HTBOTTOMLEFT = 16;
public const int HTBOTTOMRIGHT = 17;
public const int HTBORDER = 18;
public const int HTREDUCE = HTMINBUTTON;
public const int HTZOOM = HTMAXBUTTON;
public const int HTSIZEFIRST = HTLEFT;
public const int HTSIZELAST = HTBOTTOMRIGHT;
public const int HTOBJECT = 19;
}

[StructLayout(LayoutKind.Sequential)]
public struct WinAPI_NCCALCSIZE_PARAMS {
public WinAPI_RECT rgrc0, rgrc1, rgrc2;
public IntPtr lppos;
}

public struct WinAPI_SWP {
public const int SWP_NOSIZE = 0x0001;
public const int SWP_NOMOVE = 0x0002;
public const int SWP_NOZORDER = 0x0004;
public const int SWP_NOREDRAW = 0x0008;
public const int SWP_NOACTIVATE = 0x0010;
public const int SWP_FRAMECHANGED = 0x0020; // The frame changed: send
WM_NCCALCSIZE
public const int SWP_DRAWFRAME = SWP_FRAMECHANGED;
public const int SWP_SHOWWINDOW = 0x0040;
public const int SWP_HIDEWINDOW = 0x0080;
public const int SWP_NOCOPYBITS = 0x0100;
public const int SWP_NOOWNERZORDER = 0x0200; // Don't do owner Z ordering
public const int SWP_NOREPOSITION = SWP_NOOWNERZORDER;
public const int SWP_NOSENDCHANGING = 0x0400; // Don't send
WM_WINDOWPOSCHANGING
}

public enum WinAPI_WM {
WM_NCCALCSIZE = 0x0083,
WM_NCHITTEST = 0x0084,
WM_NCLBUTTONDOWN = 0x00A1,
WM_NCLBUTTONUP = 0x00A2,
WM_NCMOUSEMOVE = 0x00A0,
WM_NCPAINT = 0x0085,

WM_LBUTTONDOWN = 0x0201,
WM_MOUSEMOVE = 0x0200
}

lukasz

Użytkownik "Joey Callisay" <hcal...@codex-systems.com> napisał w wiadomości
news:eXTiczVm...@TK2MSFTNGP09.phx.gbl...

Joey Callisay

unread,
Sep 13, 2004, 5:58:34 AM9/13/04
to
oh my! I expected that MFC methods will come into this scenario, I didn't
expect it to be this complicated
(since I don't have any background on these methods). Problem is, nobody in
our team is well-verse on these,
I think I might settle with a dummy container panel to resolve this issue.

Thanks a lot for your response, I'll save this one on my reference project
collection for future use.

"lukasz" <bbl...@op.pl> wrote in message
news:uJ75dLXm...@TK2MSFTNGP14.phx.gbl...

Joey Callisay

unread,
Sep 28, 2004, 12:03:59 AM9/28/04
to
I finally decided to use this implementation:

Some questions: What is the definition for WinAPI_RECT, I believe you
forgot to declare this datatype where the Top, Bottom, Right and Left are
set-able unlike System.Drawing.Rectangle structure.

Should I declare it as just a struct based on RECT structure of MFC like
this:

[StructLayout(LayoutKind.Sequential)]
public struct WinAPI_RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}

thanks a lot!

"lukasz" <bbl...@op.pl> wrote in message
news:uJ75dLXm...@TK2MSFTNGP14.phx.gbl...

lukasz

unread,
Sep 28, 2004, 5:15:02 AM9/28/04
to
That's correct. I cut out fragments and did not check whether this excerpt
works, so let me know if you hit upon other problems.

lukasz


Użytkownik "Joey Callisay" <hcal...@codex-systems.com> napisał w wiadomości

news:uIrNwARp...@TK2MSFTNGP15.phx.gbl...

Joey Callisay

unread,
Sep 28, 2004, 6:17:44 AM9/28/04
to
Thanks for your response.
FYI, currently I have two references, your code and this: http://www.syncfusion.com/FAQ/WinForms/FAQ_c41c.asp#q1027q
And I am not well versed with MFC, I just discovered how to define a wrapper class on the used static methods from MFC.
 
I am having a problem with Repainting of my control.  It is a custom panel with custom borders following your code so I can use docking on its child controls properly.  You only provided an InvalidateNC method to invalidate the non-client area of the control.  I just bound the said method on the setter of my border style property and executing a "this.Invalidate(true)" after that to refresh its child controls.  The control is working fine for the first few seconds, however, afterwards, there is some refresh happening which does some repainting on my control (especially its clientarea).  The control's clientarea is repainted with the control's backcolor.  These are obviously design time problems.
 
FYI:  I am not overriding the OnPaint method of my custom container control
 
Here is the code for my WndProc method
 

protected override void WndProc(ref Message m)

{

            Point pt;

            switch(m.Msg)

            {

                        case (int) WinAPI_WM.WM_NCCALCSIZE: // Client Rectangle size manipulation??

                                    //JOEY: Calculate first the border width

                                    this.CalculateBorderWidth();

                                    // The update region is clipped to the window frame. When wParam is 1, the entire window frame needs to be updated

                                    if ( m.WParam == IntPtr.Zero )

                                    {

                                                WinAPI_NCCALCSIZE_PARAMS csp;

                                                csp = (WinAPI_NCCALCSIZE_PARAMS)Marshal.PtrToStructure( m.LParam, typeof(WinAPI_NCCALCSIZE_PARAMS));

                                                csp.rgrc0.Top += nBorderHeight;

                                                csp.rgrc0.Bottom -= nBorderHeight;

                                                csp.rgrc0.Left += nBorderWidth;

                                                csp.rgrc0.Right -= nBorderWidth;

                                                Marshal.StructureToPtr( csp, m.LParam, false );

                                    }

                                    else if (m.WParam == new IntPtr(1))

                                    {

                                                WinAPI_NCCALCSIZE_PARAMS csp;

                                                csp = (WinAPI_NCCALCSIZE_PARAMS)Marshal.PtrToStructure( m.LParam, typeof(WinAPI_NCCALCSIZE_PARAMS));

                                                csp.rgrc0.Top += nBorderHeight;

                                                csp.rgrc0.Bottom -= nBorderHeight;

                                                csp.rgrc0.Left += nBorderWidth;

                                                csp.rgrc0.Right -= nBorderWidth;

                                                Marshal.StructureToPtr( csp, m.LParam, false );

                                    }

                                    break;

                        case (int) WinAPI_WM.WM_NCPAINT:

                                    this.CalculateBorderWidth();

                                    IntPtr hDC = NativeMethods.GetWindowDC( m.HWnd );

                                    Graphics g = Graphics.FromHdc( hDC );

                                    // border

                                    Border3DStyle enBorderStyle = Border3DStyle.Adjust;

                                    if (m_sdroBackColor == Color.Transparent)

                                    {

                                                m_sdroBackColor = (this.TopLevelControl != null) ? this.TopLevelControl.BackColor : this.BackColor;

                                    }

                                    if (m_enBorderStyle == CFCGlobalResources.CdxEBorderStyles.Custom)

                                    {

                                                // Draw custom border

                                                Rectangle rct = new Rectangle(0, 0, this.Width, this.Height);

                                                ControlPaint.DrawBorder(g, rct,

                                                            this.m_sdroOuterBorderColor, m_szOuterBorderSize.Width, ButtonBorderStyle.Solid,

                                                            this.m_sdroOuterBorderColor, m_szOuterBorderSize.Height, ButtonBorderStyle.Solid,

                                                            this.m_sdroOuterBorderColor, m_szOuterBorderSize.Width, ButtonBorderStyle.Solid,

                                                            this.m_sdroOuterBorderColor, m_szOuterBorderSize.Height, ButtonBorderStyle.Solid);

                                                rct.Inflate(this.m_szOuterBorderSize.Width * -1 , this.m_szOuterBorderSize.Height * -1);

                                                ControlPaint.DrawBorder(g, rct,

                                                            this.m_sdroInnerBorderColor, m_szInnerBorderSize.Width, ButtonBorderStyle.Solid,

                                                            this.m_sdroInnerBorderColor, m_szInnerBorderSize.Height, ButtonBorderStyle.Solid,

                                                            this.m_sdroInnerBorderColor, m_szInnerBorderSize.Width, ButtonBorderStyle.Solid,

                                                            this.m_sdroInnerBorderColor, m_szInnerBorderSize.Height, ButtonBorderStyle.Solid);

                                    }

                                    else

                                    {

                                                switch (m_enBorderStyle)

                                                {

                                                            case CFCGlobalResources.CdxEBorderStyles.Etched:

                                                                        enBorderStyle = Border3DStyle.Etched;

                                                                        break;

                                                            case CFCGlobalResources.CdxEBorderStyles.Raised:

                                                                        enBorderStyle = Border3DStyle.RaisedInner;

                                                                        break;

                                                            case CFCGlobalResources.CdxEBorderStyles.Sunken:

                                                                        enBorderStyle = Border3DStyle.SunkenOuter;

                                                                        break;

                                                            case CFCGlobalResources.CdxEBorderStyles.Flat:

                                                                        enBorderStyle = Border3DStyle.Flat;

                                                                        break;

                                                }

                                                Rectangle rct = new Rectangle(0, 0, this.Width, this.Height);

                                                ControlPaint.DrawBorder3D(g, rct, enBorderStyle, Border3DSide.All);

                                    }

                                    NativeMethods.ReleaseDC( m.HWnd, hDC );

                                    this.Invalidate();

                                    break;

                        case (int)WinAPI_WM.WM_NCHITTEST:

                                    m.Result = (IntPtr)WinAPI_HT.HTBORDER;

                                    return;

                        case (int)WinAPI_WM.WM_NCMOUSEMOVE:

                                    pt = PointToClient( new Point( m.LParam.ToInt32() ) );

                                    pt.Offset(nBorderWidth, nBorderHeight);

                                    // ...

                                    break;

                        case (int)WinAPI_WM.WM_NCLBUTTONDOWN:

                                    pt = PointToClient( new Point( m.LParam.ToInt32() ) );

                                    pt.Offset(nBorderWidth, nBorderHeight);

                                    // ...

                                    break;

            }

            base.WndProc (ref m);

}

 

My other reference overrides the readonly CreateParams property of Control to declare a border, isn't it needed in your implementation?  I really don't know anything about his CreateParams setting.

 

Thanx a lot for your help!

 
 
> That's correct. I cut out fragments and did not check whether this excerpt
> works, so let me know if you hit upon other problems.
>
> lukasz
>
>
> U¿ytkownik "Joey Callisay" <hcal...@codex-systems.com> napisa³ w wiadomo¶ci
>
news:uIrNwARp...@TK2MSFTNGP15.phx.gbl...
> > > U¿ytkownik "Joey Callisay" <hcal...@codex-systems.com> napisa³ w
> > wiadomo¶ci
> > >
news:eXTiczVm...@TK2MSFTNGP09.phx.gbl...

Joey Callisay

unread,
Sep 28, 2004, 11:47:30 PM9/28/04
to
And by the way, I don't see the point on your if and else statements for
WM_NCCALCSIZE which are the same. Can you give me some info regarding the
difference between message.WParam == IntPtr.Zero and message.WParam ==
IntPtr(1)

Thanks!

"lukasz" <bbl...@op.pl> wrote in message

news:%23nM7iuT...@tk2msftngp13.phx.gbl...

lukasz

unread,
Sep 29, 2004, 6:20:21 AM9/29/04
to
See
http://groups.google.pl/groups?selm=OnRNaGfDEHA.1600%40tk2msftngp13.phx.gbl

I have same code in both cases because it was debug code that I were to
investigate further.


Użytkownik "Joey Callisay" <hcal...@codex-systems.com> napisał w wiadomości

news:uj5VPcdp...@TK2MSFTNGP14.phx.gbl...

lukasz

unread,
Sep 29, 2004, 6:25:49 AM9/29/04
to
I have not encountered any problems with my control, and I do not override
the OnPaint method either. Can you be more specific about the issue?

lukasz


Uzytkownik "Joey Callisay" <hcal...@codex-systems.com> napisal w wiadomosci
news:#$5FnRUpE...@TK2MSFTNGP14.phx.gbl...

{

Point pt;

switch(m.Msg)

{

this.CalculateBorderWidth();

{

WinAPI_NCCALCSIZE_PARAMS
csp;

csp.rgrc0.Top +=
nBorderHeight;

csp.rgrc0.Bottom -=
nBorderHeight;

csp.rgrc0.Left +=
nBorderWidth;

csp.rgrc0.Right -=
nBorderWidth;

}

{

WinAPI_NCCALCSIZE_PARAMS
csp;

csp.rgrc0.Top +=
nBorderHeight;

csp.rgrc0.Bottom -=
nBorderHeight;

csp.rgrc0.Left +=
nBorderWidth;

csp.rgrc0.Right -=
nBorderWidth;

}

break;

case (int) WinAPI_WM.WM_NCPAINT:

this.CalculateBorderWidth();

// border

Border3DStyle enBorderStyle =
Border3DStyle.Adjust;

if (m_sdroBackColor ==
Color.Transparent)

{

}

if (m_enBorderStyle ==
CFCGlobalResources.CdxEBorderStyles.Custom)

{

// Draw custom border

ControlPaint.DrawBorder(g,
rct,


this.m_sdroOuterBorderColor, m_szOuterBorderSize.Width,
ButtonBorderStyle.Solid,


this.m_sdroOuterBorderColor, m_szOuterBorderSize.Height,
ButtonBorderStyle.Solid,


this.m_sdroOuterBorderColor, m_szOuterBorderSize.Width,
ButtonBorderStyle.Solid,


this.m_sdroOuterBorderColor, m_szOuterBorderSize.Height,
ButtonBorderStyle.Solid);

ControlPaint.DrawBorder(g,
rct,


this.m_sdroInnerBorderColor, m_szInnerBorderSize.Width,
ButtonBorderStyle.Solid,


this.m_sdroInnerBorderColor, m_szInnerBorderSize.Height,
ButtonBorderStyle.Solid,


this.m_sdroInnerBorderColor, m_szInnerBorderSize.Width,
ButtonBorderStyle.Solid,


this.m_sdroInnerBorderColor, m_szInnerBorderSize.Height, ButtonBorderStyle.S
olid);

}

else

{

switch (m_enBorderStyle)

{

case
CFCGlobalResources.CdxEBorderStyles.Etched:


enBorderStyle = Border3DStyle.Etched;


break;

case
CFCGlobalResources.CdxEBorderStyles.Raised:


enBorderStyle = Border3DStyle.RaisedInner;


break;

case
CFCGlobalResources.CdxEBorderStyles.Sunken:


enBorderStyle = Border3DStyle.SunkenOuter;


break;

case
CFCGlobalResources.CdxEBorderStyles.Flat:


enBorderStyle = Border3DStyle.Flat;


break;

}

ControlPaint.DrawBorder3D(g,
rct, enBorderStyle, Border3DSide.All);

}

NativeMethods.ReleaseDC( m.HWnd, hDC );

this.Invalidate();

break;

case (int)WinAPI_WM.WM_NCHITTEST:

m.Result = (IntPtr)WinAPI_HT.HTBORDER;

return;

case (int)WinAPI_WM.WM_NCMOUSEMOVE:

pt.Offset(nBorderWidth, nBorderHeight);

// ...

break;

case (int)WinAPI_WM.WM_NCLBUTTONDOWN:

pt.Offset(nBorderWidth, nBorderHeight);

// ...

break;

}

base.WndProc (ref m);

}

> Użytkownik "Joey Callisay" <hcal...@codex-systems.com> napisał w
wiadomości

> > > Użytkownik "Joey Callisay" <hcal...@codex-systems.com> napisał w
> > wiadomości

Joey Callisay

unread,
Sep 29, 2004, 9:28:42 PM9/29/04
to
thanks for the link. I'll try to resolve my issue first then when I give
up, I'll ask you again, :p. I'm beginning to get the big picture of this
non-client window...

"lukasz" <bbl...@op.pl> wrote in message

news:%23r21u3g...@TK2MSFTNGP10.phx.gbl...

Joey Callisay

unread,
Oct 5, 2004, 10:36:46 PM10/5/04
to
I've reposted another query lucasz, please help if you can, thanks..

"Joey Callisay" <hcal...@codex-systems.com> wrote in message
news:%237Q7Tzo...@TK2MSFTNGP14.phx.gbl...

Joey Callisay

unread,
Oct 5, 2004, 10:53:48 PM10/5/04
to
Oops, I just got it, finally.

Instead of invalidating just the control after painting the custom borders,
I used the overloaded Invalidate(true) method to repaint its child controls
(since it is a container control). It's now working. My final question is,
is it efficient painting?


"Joey Callisay" <hcal...@codex-systems.com> wrote in message

news:OlEQU10q...@TK2MSFTNGP10.phx.gbl...

Joey Callisay

unread,
Oct 5, 2004, 11:37:38 PM10/5/04
to
I guess it was not efficient since I am encountering flicker if I do have a
number (10+) of controls as the container's child controls. Please help
again...

"Joey Callisay" <hcal...@codex-systems.com> wrote in message

news:en7s1%230qEH...@TK2MSFTNGP12.phx.gbl...

lukasz

unread,
Oct 6, 2004, 2:53:11 PM10/6/04
to
I don't know how and when you repaint the control so I can't help you much.
Try searching the news for container controls and the flickering effect.


Użytkownik "Joey Callisay" <hcal...@codex-systems.com> napisał w wiadomości

news:u1glVX1q...@TK2MSFTNGP12.phx.gbl...

Dasirr

unread,
Nov 7, 2004, 7:33:02 AM11/7/04
to
To change the ClientArea in .NET you have to override WndProc and handle
WinApi messages. This is a bit complex and takes some time to figure out.
When you have accomplished this then you will notice another problem: The
painting you do on the NoNClientArea is not double buffered so you will have
flickering. This can be handled too with complex WinApi code, but before you
have handled all this you have wasted some expensive development hours.

To make this a bit easier there is another solution: There is a library
available which handles all this for you in a very simple ContainerControl,
named QContainerControlBase. You can adjust the ClientArea and paint on the
Non-ClientArea in the OnPaintNonClientArea event. It even makes it possible
to make the control resizable for the user, so you won’t need a Splitter
control.

The library is called Qios.DevSuite.Components and is developed by a
Microsoft Gold Certified Partner, named QIOS. Next to the possibility to
create ContainerControls it contains a StatusBar, MainMenu, ContextMenu,
DockableWindows and Panels. It supports Windows Themes and the layout and
colors of the controls are fully configurable.

You can download the library from http://developers.qios.nl and give it a try.

Here I give you an example of how you can inherit from QContainerControlBase
and adjust the NonClientAera done:

/// <summary>
/// A container control that inherits from QContainerControlBase so the
ClientArea
/// </summary>
public class MyControl : QContainerControl
{

public MyControl()
{
//Decide whether the user can size the Control. This is a nice feature so
//the user can runtime resize the Control without a Splitter. It updates
//the control immediatly, so the user sees the effect while resizing...

//Because those are true, make sure to override ResizeBorderWidth
this.CanSizeRight = true;
this.CanSizeTop = true;
this.CanSizeBottom = true;
this.CanSizeLeft = true;
}

/// <summary>
/// Override the ClientAreaMargin properties, so the client-area is
adjusted.
/// </summary>
protected override int ClientAreaMarginBottom
{
get { return 10; }
}

protected override int ClientAreaMarginTop
{
get { return 10; }
}

protected override int ClientAreaMarginRight
{
get { return 10; }
}

protected override int ClientAreaMarginLeft
{
get { return 10; }
}

/// <summary>
/// Because the user can resize the Control, give the ResizeBorderWidth.
This is the width
/// of the border that the user can use to resize. Returning 0 means the
user can't resize.
/// </summary>
protected override int ResizeBorderWidth
{
get { return 5; }
}

/// <summary>
/// Because there is a NonClientArea, you can override the
OnPaintNonClientArea to do custom
/// painting. This happens double-buffered, so no flickering!
/// </summary>
protected override void OnPaintNonClientArea(PaintEventArgs e)
{
base.OnPaintNonClientArea (e);
//
//Do you custom drawing here...
//
}

}

0 new messages