Runtime Resizable Panel Control

Below is a complete resizable panel the can be resized on the right and bottom. It uses the windows SysCommand message and some little know options to cause the window (control) to resize.

If you want to allow moving or resizing in other directions, then extend the mouse location check and call the appropriate syscommand values.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
 
namespace YourAssembly
{
    public partial class ResizablePanel : Panel
    {
        private Boolean _ResizeParent;
 
        private class NativeCalls
        {
            [DllImport("USER32.DLL", EntryPoint = "SendMessage")]
            public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, ref int lParam);
            [DllImport("user32")]
            public static extern int ReleaseCapture(IntPtr hwnd);
            public const int WM_SYSCOMMAND = 0×0112;
            public const int SC_DRAGMOVE = 0xF012;
            public const int SC_DRAGSIZE_N = 0xF003;
            public const int SC_DRAGSIZE_S = 0xF006;
            public const int SC_DRAGSIZE_E = 0xF002;
            public const int SC_DRAGSIZE_W = 0xF001;
            public const int SC_DRAGSIZE_NW = 0xF004;
            public const int SC_DRAGSIZE_NE = 0xF005;
            public const int SC_DRAGSIZE_SW = 0xF007;
            public const int SC_DRAGSIZE_SE = 0xF008;
        }
 
        public Boolean ResizeParent
        {
            get { return _ResizeParent; }
            set { _ResizeParent = value; }
        }
 
        public ResizablePanel()
        {
            InitializeComponent();
            MinimumSize = new Size(50, 50);
            Margin = new Padding(0, 0, 0, 0);
            Padding = new Padding(0, 0, 3, 3);
            BackColor = SystemColors.ControlLight;
        }
 
        private enum MousePos {NoWhere, Right, Bottom, BottomRight}
 
        private MousePos GetMousePos(Point location)
        {
            MousePos result = MousePos.NoWhere;
 
            Rectangle TestRect;
 
            int RightSize = Padding.Right;
            int BottomSize = Padding.Bottom;
 
            // Resize right border
            TestRect = new Rectangle(Width – RightSize, 0, Width – RightSize, Height – BottomSize);
            if (TestRect.Contains(location)) result = MousePos.Right;
 
            // Resize bottom border
            TestRect = new Rectangle(0, Height – BottomSize, Width – RightSize, Height);
            if (TestRect.Contains(location)) result = MousePos.Bottom;
 
            // Resize bottom Corner
            TestRect = new Rectangle(Width – RightSize, Height -BottomSize, Width, Height);
            if (TestRect.Contains(location)) result = MousePos.BottomRight;
            return result;
        }
 
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
 
            IntPtr hwnd = this.Handle;
 
            if ((ResizeParent) && (this.Parent != null) && (this.Parent.IsHandleCreated))
            {
                hwnd = Parent.Handle;
            }
 
            int nul = 0;
            MousePos mousePos = GetMousePos(e.Location);
            switch (mousePos)
            {
                case MousePos.Right:
                    {
                        NativeCalls.ReleaseCapture(hwnd);
                        NativeCalls.SendMessage(hwnd, NativeCalls.WM_SYSCOMMAND, NativeCalls.SC_DRAGSIZE_E, ref nul);
                    } break;
                case MousePos.Bottom:
                    {
                        NativeCalls.ReleaseCapture(hwnd);
                        NativeCalls.SendMessage(hwnd, NativeCalls.WM_SYSCOMMAND, NativeCalls.SC_DRAGSIZE_S, ref nul);
                    } break;
                case MousePos.BottomRight:
                    {
                        NativeCalls.ReleaseCapture(hwnd);
                        NativeCalls.SendMessage(hwnd, NativeCalls.WM_SYSCOMMAND, NativeCalls.SC_DRAGSIZE_SE, ref nul);
                    } break;
            }
 
        }
 
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
 
            MousePos mousePos = GetMousePos(e.Location);
            switch (mousePos)
            {
                case MousePos.Right: Cursor = Cursors.SizeWE; break;
                case MousePos.Bottom: Cursor = Cursors.SizeNS; break;
                case MousePos.BottomRight: Cursor = Cursors.SizeNWSE; break;
                default: Cursor = Cursors.Default; break;
            }
        }
 
        protected override void OnResize(EventArgs eventargs)
        {
            base.OnResize(eventargs);
            if (this.Width < this.MinimumSize.Width) this.Width = this.MinimumSize.Width;
            if (this.Height < this.MinimumSize.Height) this.Height = this.MinimumSize.Height;
        }
 
        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            Cursor = Cursors.Default;
        }
    }
 
 
}

2 Responses to “Runtime Resizable Panel Control”

  • Mike:

    Very helpful, thank you!

  • Devubha Manek:

    It’s great! what I am looking for. I have modified your code to make it movable but when I have done that change the Mouse click event is not firing can you help me in this here is complete code:

    ///
    /// Resizable and Movable Panel
    ///
    public partial class ResizablePanel : Panel
    {
    // Do Resize parent or not
    private Boolean _ResizeParent;

    ///
    /// This class is native call class in which Win32 related constant and function are declared
    ///
    private class NativeCalls
    {
    [DllImport("USER32.DLL", EntryPoint = "SendMessage")]
    public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, ref int lParam);
    [DllImport("user32")]
    public static extern int ReleaseCapture(IntPtr hwnd);
    public const int WM_SYSCOMMAND = 0×0112;
    public const int SC_DRAGMOVE = 0xF012;
    public const int SC_DRAGSIZE_N = 0xF003;
    public const int SC_DRAGSIZE_S = 0xF006;
    public const int SC_DRAGSIZE_E = 0xF002;
    public const int SC_DRAGSIZE_W = 0xF001;
    public const int SC_DRAGSIZE_NW = 0xF004;
    public const int SC_DRAGSIZE_NE = 0xF005;
    public const int SC_DRAGSIZE_SW = 0xF007;
    public const int SC_DRAGSIZE_SE = 0xF008;

    // This are required for Move Functionality
    public const int WM_NCLBUTTONDOWN = 0xA1;
    public const int HTCAPTION = 2;
    }

    ///
    /// Resize parent or Not
    ///
    public Boolean ResizeParent
    {
    get { return _ResizeParent; }
    set { _ResizeParent = value; }
    }

    ///
    /// Constructor for Resizable Panel
    ///
    public ResizablePanel()
    {
    InitializeComponent();
    MinimumSize = new Size(50, 50);
    Margin = new Padding(0, 0, 0, 0);
    Padding = new Padding(0, 0, 3, 3);
    BackColor = SystemColors.ControlLight;
    }

    // Enum which indicate in which direction need to resize
    private enum MousePos {NoWhere, Left, Right, Top, Bottom, BottomRight,Middle}

    ///
    /// Get Movuse Position based on that we will decide which action need to perform
    ///
    ///
    ///
    private MousePos GetMousePos(Point location)
    {
    MousePos result = MousePos.NoWhere;

    Rectangle TestRect;

    int LeftSize = Padding.Left;
    int RightSize = Padding.Right;
    int TopSize = Padding.Top;
    int BottomSize = Padding.Bottom;

    // Resize left border
    TestRect = new Rectangle(Width – LeftSize, 0, Width – LeftSize, Height – BottomSize);
    if (TestRect.Contains(location)) result = MousePos.Left;

    // Resize right border
    TestRect = new Rectangle(Width – RightSize, 0, Width – RightSize, Height – BottomSize);
    if (TestRect.Contains(location)) result = MousePos.Right;

    // Resize bottom border
    TestRect = new Rectangle(0, Height – BottomSize, Width – RightSize, Height);
    if (TestRect.Contains(location)) result = MousePos.Bottom;

    // Resize bottom Corner
    TestRect = new Rectangle(Width – RightSize, Height -BottomSize, Width, Height);
    if (TestRect.Contains(location)) result = MousePos.BottomRight;

    // Move For Middle Mouse
    TestRect = new Rectangle(10, 10, Width – 20, Height – 20);
    if (TestRect.Contains(location)) result = MousePos.Middle;

    return result;
    }

    ///
    /// Mouse down event of the Panel
    ///
    ///
    protected override void OnMouseDown(MouseEventArgs e)
    {
    base.OnMouseDown(e);

    IntPtr hwnd = this.Handle;

    if ((ResizeParent) && (this.Parent != null) && (this.Parent.IsHandleCreated))
    {
    hwnd = Parent.Handle;
    }

    int nul = 0;
    MousePos mousePos = GetMousePos(e.Location);
    switch (mousePos)
    {
    case MousePos.Left:
    {
    NativeCalls.ReleaseCapture(hwnd);
    NativeCalls.SendMessage(hwnd, NativeCalls.WM_SYSCOMMAND, NativeCalls.SC_DRAGSIZE_W, ref nul);
    } break;
    case MousePos.Right:
    {
    NativeCalls.ReleaseCapture(hwnd);
    NativeCalls.SendMessage(hwnd, NativeCalls.WM_SYSCOMMAND, NativeCalls.SC_DRAGSIZE_E, ref nul);
    } break;
    case MousePos.Bottom:
    {
    NativeCalls.ReleaseCapture(hwnd);
    NativeCalls.SendMessage(hwnd, NativeCalls.WM_SYSCOMMAND, NativeCalls.SC_DRAGSIZE_S, ref nul);
    } break;
    case MousePos.BottomRight:
    {
    NativeCalls.ReleaseCapture(hwnd);
    NativeCalls.SendMessage(hwnd, NativeCalls.WM_SYSCOMMAND, NativeCalls.SC_DRAGSIZE_SE, ref nul);
    } break;
    case MousePos.Middle:
    {
    NativeCalls.ReleaseCapture(hwnd);
    NativeCalls.SendMessage(hwnd, NativeCalls.WM_NCLBUTTONDOWN, NativeCalls.HTCAPTION, ref nul);
    } break;
    }
    }

    ///
    /// Mouse move event of the panel
    ///
    ///
    protected override void OnMouseMove(MouseEventArgs e)
    {
    base.OnMouseMove(e);

    MousePos mousePos = GetMousePos(e.Location);
    switch (mousePos)
    {
    case MousePos.Left: Cursor = Cursors.SizeWE; break;
    case MousePos.Right: Cursor = Cursors.SizeWE; break;
    case MousePos.Bottom: Cursor = Cursors.SizeNS; break;
    case MousePos.BottomRight: Cursor = Cursors.SizeNWSE; break;
    case MousePos.Middle: Cursor = Cursors.Hand; break;
    default: Cursor = Cursors.Default; break;
    }
    }

    ///
    /// Mouse move event of the panel
    ///
    ///
    protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
    {
    MessageBox.Show(”Clicked!”);
    base.OnPreviewKeyDown(e);

    }

    ///
    /// Set Resize bound for the panel
    ///
    ///
    protected override void OnResize(EventArgs eventargs)
    {
    base.OnResize(eventargs);
    if (this.Width < this.MinimumSize.Width) this.Width = this.MinimumSize.Width;
    if (this.Height < this.MinimumSize.Height) this.Height = this.MinimumSize.Height;
    }

    ///
    /// Mouse Leave event of the Panel
    ///
    ///
    protected override void OnMouseLeave(EventArgs e)
    {
    base.OnMouseLeave(e);
    Cursor = Cursors.Default;
    }
    }

Leave a Reply