Click here to Skip to main content
13,894,185 members
Click here to Skip to main content
Add your own
alternative version


206 bookmarked
Posted 22 Feb 2007
Licenced CPOL

Add docking and floating support easely and quickly with DockExtender

, 4 Jul 2007
Rate this:
Please Sign up or sign in to vote.
DockExtender allows you to add docking / floating / resizing behaviour to any control on your win form with just a few lines of code, making it very easy for your application to support basic docking features.
  • Download demo + source files - 33.9 KB

    Sample Image - DockExtender1.png


    So you are looking to add 'control docking' features to your winform application? E.g. you want to have a floating toolbar or allow users to dock parts of your form at a different location at runtime? This tiny and lightweight control extender for C# 2.0 will help you enable these features.

    I wrote this solution with the following purposes/constraints in mind:

    • Docking/Floating behaviour must be easy to incorporate and use in new and existing winform projects
    • It may not pose too many constraints on the structuring of the form layout
    • The code must be lightweight. That is, have a small footprint and require few resources; i.e. may not be dependent on external, magic libraries.
    • Dockable controls must support resizing
    • The code must be easy to use: steep learning curve!
    • Use native C# where possible.

    In order to support these constraints I had to cut some features. E.g. this solution will not allow docking of single tab pages in tab controls. Also because of the basic programmatic interface, the client has little control over what happens with the floating/docking controls. So if you are looking for a more full blown (but also bloated and much heavier) solution that supports all types of docking you might want to consider Weifen Luo's DockManager on source forge or commercial products.

    Still interested in a low impact, easy to use, and lightweight approach? This solution will allow you to practically make any control dockable/floatable in just a few lines of code! So how does it work you ask? Just keep on reading.

    Using the code

    It's simple, first setup the project: create a new winform project, add the DockExtender.cs, Floaty.cs and Overlay.cs files to your project. Then, for the sake of the example, add a ToolStrip control to your form.

    Then add the ControlExtenders namespace to the form and declare the DockExtender object in the form. Then in the constructor of your form create a new DockExtender object and Attach the (container) control to it that you want make dockable/floatable (the toolstrip in this example). Once it is attached, the DockExtender class will extend the behaviour of your attached control and will take care of the floating/docking behaviour for you. The following code will make a toolbar control dockable/floating:

    //add namespace
    using ControlExtenders;
    // declare dockExtender as a member of the form
         DockExtender dockExtender;
    // in the Form1() constructor create the DockExtender to manage controls
    // on for the 'dockHost'
         dockExtender = new DockExtender(this); // 'this' is Form1
         // Attach the toolStrip1 toolbar. The 2nd argument is the handle.
         // This will make the whole toolstrip draggable. A floaty object is
         // returned.
         IFloaty floaty = dockExtender.Attach(toolStrip1);

    There, that's it! Two lines of code to make your first dockable/floatable control!

    Drag and resize

    Basically all you need is what I call a 'Container' control. It represents the part of your form that can be made floatable/dockable. In order to drag the Container control around with the mouse you needs a 'Handle', this is basically the Container's caption/griphandle. Of course if you supply the container itself as the handle, the whole container will become the handlebar (as in the example above)!

    Now the beauty of this solution is that the 'Container' control and 'Handle' control can be of any type (as long as it is derived from ScrollableControl and Control respectively)! In my demo for simplicity's sake, I used a Panel for the container and a Label (hosted on the panel) for the handle. (Note: Obviously the handle looks rather plain, but it would be very easy to make it nicer looking. This is beyond the scope of this article though).

    To make it more interesting it would be very handy to allow a docked container control to be resized by the user. The DockExtender supports this, yet there is one restriction. You can only use a Splitter control (or a subclass of Splitter) with the DockExtender. E.g.:

    // Attach the a panel as container, a label as handlebar and a splitter to 
    // resize the control to make panel1 dockable/floatable and resizable
    IFloaty floaty = dockExtender.Attach(panel1, label1, splitter1);

    Now when executing this code, and docking the panel1 on the form your will notice that the splitter is automatically positioned on top of the panel, allowing the user to resize the panel.

    Docking (Z-)order

    By default containers are docked on the inside of the docking host (ie. the form). This means, that if other controls are already docked in the host, the container will be docked on the inside of the host (bring to front).

    In some cases you may not want to dock only on the inside, but rather on the outside. E.g. toolbars or menus are typically docked on the outside (sent to back). To allow this we can use the returned floaty object to set some additional properties: floaty.DockOnInside:

    // Attach the toolStrip1 toolbar as container and handle
    IFloaty floaty = dockExtender.Attach(toolStrip1);
    // supply false for 'dockOnInside'-flag. Allow docking on the outside of the 
    // docking host
    floaty.DockOnInside = false; // dock to outside

    If the DockOnInside is set to false the control will be set to the back, making it dock on the outside of the dockhost.

    Docking event

    So in this example the toolbar will be docked on the outside. This raises a problem though, because this means that for instance the menubar will be docked below the toolbar which is not desired. In order to cope with this problem, a 'Docking' event is raised when a control is docked. This allows the client to set the correct Z-Ordering of the non-dockable controls, such as the menubar, statusbar and the inner document.

    To capture this event, you need to do the following:

    // get a reference to the floating control to which the container is attached 
    // by the DockExtender
    IFloaty floaty = dockExtender.Attach(panel1, label1, splitter1); 
    // the floaty will raise a Docking event when it is docking.
    floaty.Docking += new EventHandler(floaty_Docking);
    void  floaty_Docking(object sender, EventArgs e)
        // make sure the ZOrder remains intact for the menubar and statusbar

    Now the menuStrip and statusStrip will always be positioned correctly with the correct Z-Order.

    More features

    A few more trivial features are available that I will not explain in depth here. In order to have more control over the display of the floaty/container, you can programmatically Show() and Hide() a IFloaty object, or use the dockManager's Show(container) /Hide(container) method to display the container control. Also you can iterate through the list of registered DockExtender.Floaties.

    Sources and Demo

    The sources project contains all sources of the DockExtender and of the demo project, no external or magic libraries are needed! Feel free to use and adapt this code for your own purposes.

    How does it work?

    For those that are interested I will explain here how the internals of the DockExtender work. The DockExtender consists of three main classes: 'DockExtender', 'Floaty' and 'Overlay'. DockExtender is more a management class that manages the floaties. For each container that is attached, a corresponding Floaty object is created to which the container is attached.

    The Floaty does most of the work. The Overlay class is used by the floaty to display the designated docking area's. Basically there are the following types of actions:

    • Attach the container
    • Go from docked state to floating state
    • Select designated docking area
    • Go from floating state to docked state

    Attach the container

    1. The state of the container is stored in the DockState struct. This allows to restore to the previous state if necessary.
    2. The Floaty will attach mouse move event handlers to the handle and track the movement of the mouse when it is hovering over the handle

    From Docked to Floating

    1. Mouse move events are triggered by the handle
    2. Resize the floaty form to the size of the docked control
    3. Send a Left-button-up windows message to the handle so it will stop firing mouse move events (requires Win API)
    4. Re-parent the control into the floaty and dock it as Filled
    5. Position the floaty under the mouse cursor
    6. Hide the handle
    7. Send a system command windows message to the floaty to start the size-move loop (requires Win API)
    8. The mouse is now dragging the floaty

    Select designated docking area

    1. Get the mouse position
    2. Check over which attached forms/controls the mouse is hovering
    3. Determine the maximum potential docking area.
    4. If the mouse is moving into a designated area, calculate the position and size of the overlay
    5. Present the overlay control for the designated area
    6. Dock the control

    From Floating to Docked

    1. Set the DockState parameters to the new docking area
    2. Re-parent the container into the designated control/form
    3. Show the handle
    4. Hide the floaty form
    5. Set the Z-Order of the container
    6. Fire the Docking event

    Points of Interest

    Using an 'extender' approach makes it so much easier to develope. It means you are no longer required to use specific controls or derive from them in order to extend their behaviour. This way any control can be extended fast and easy without a lot of code modifications, and is therefore very well suited to be incorporated into existing projects that require these extended features.

    Origionally the idea was to allow docking also inside containers, but this gave a number of new challanges to tackle, so I left it out of this demo by default. The code can however still be triggired by setting the floaty.DockOnHostOnly to false. Note that setting this property may result in undesired effects.

    Just one personal note I want to make here is that I saw no other way than to use the SendMessage API instead of pure c#. I prefer to write c# in pure c# and not resort to win API's, but there you have it.

    If you decide to use this code, feel free to post pointers and tips for improvements. Happy Coding!


    Version 1.0 of the DockExtender was published on the 23th of Februari 2007.

  • License

    This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


    About the Author

    Herre Kuijpers
    Architect Rubicon
    Netherlands Netherlands
    Currently Herre Kuijpers is employed at Rubicon. During his career he developed skills with all kinds of technologies, methodologies and programming languages such as c#, ASP.Net, .Net Core, VC++, Javascript, SQL, Agile, Scrum, DevOps, ALM. Currently he fulfills the role of software architect in various projects.

    Herre Kuijpers is a very experienced software architect with deep knowledge of software design and development on the Microsoft .Net platform. He has a broad knowledge of Microsoft products and knows how these, in combination with custom software, can be optimally implemented in the often complex environment of the customer.

    You may also be interested in...

    Comments and Discussions

    QuestionDocking and floating windows in win forms Pin
    Member 1228519411-Feb-19 22:46
    memberMember 1228519411-Feb-19 22:46 
    QuestionWorked Pin
    Amit Kumar27-Feb-18 0:22
    memberAmit Kumar27-Feb-18 0:22 
    GeneralThank You So Much!!! Pin
    Larx8325-May-15 22:55
    memberLarx8325-May-15 22:55 
    GeneralMessage Closed Pin
    1-Apr-14 15:58
    memberMember 102265801-Apr-14 15:58 
    GeneralMy vote of 5 Pin
    teng33887-Aug-13 15:12
    memberteng33887-Aug-13 15:12 
    GeneralMy vote of 5 Pin
    Member 816903429-Oct-12 16:30
    memberMember 816903429-Oct-12 16:30 
    QuestionUrgent help is required on how to do docking on LOAD Event Pin
    bosercv10-May-12 1:09
    memberbosercv10-May-12 1:09 
    QuestionUrgent help is required on how to do docking on LOAD Event Pin
    bosercv10-May-12 1:08
    memberbosercv10-May-12 1:08 
    QuestionImplementation using wpf Pin
    akstemptation7-Nov-11 22:32
    memberakstemptation7-Nov-11 22:32 
    AnswerRe: Implementation using wpf Pin
    Herre Kuijpers8-Nov-11 21:32
    memberHerre Kuijpers8-Nov-11 21:32 
    QuestionGreat job. How to make it work on Mono? Pin
    zengdj12-Mar-11 23:52
    memberzengdj12-Mar-11 23:52 
    GeneralSwapping control into a different parent [modified] Pin
    Nick Alexeev30-Jan-11 10:28
    professionalNick Alexeev30-Jan-11 10:28 
    GeneralRe: Swapping control into a different parent Pin
    Herre Kuijpers30-Jan-11 10:49
    memberHerre Kuijpers30-Jan-11 10:49 
    GeneralRe: Swapping control into a different parent [modified] Pin
    Nick Alexeev30-Jan-11 12:09
    professionalNick Alexeev30-Jan-11 12:09 
    GeneralRe: Swapping control into a different parent Pin
    Herre Kuijpers30-Jan-11 21:01
    memberHerre Kuijpers30-Jan-11 21:01 
    GeneralRe: Swapping control into a different parent Pin
    Nick Alexeev1-Feb-11 20:43
    professionalNick Alexeev1-Feb-11 20:43 
    GeneralDock Indicator Pin
    Nick Alexeev15-Jan-11 16:46
    professionalNick Alexeev15-Jan-11 16:46 
    GeneralRe: Dock Indicator Pin
    Herre Kuijpers16-Jan-11 0:03
    memberHerre Kuijpers16-Jan-11 0:03 
    Generalmy vote of 4 Pin
    tr021717-Dec-10 21:31
    membertr021717-Dec-10 21:31 
    GeneralFloaty Pin
    DrJBN18-Nov-10 22:33
    memberDrJBN18-Nov-10 22:33 
    QuestionSome unusual action and request solution Pin
    Sports Kuo4-Jul-10 22:41
    memberSports Kuo4-Jul-10 22:41 
    AnswerRe: Some unusual action and request solution Pin
    Herre Kuijpers5-Jul-10 3:24
    memberHerre Kuijpers5-Jul-10 3:24 
    GeneralRe: Some unusual action and request solution Pin
    Sports Kuo5-Jul-10 16:17
    memberSports Kuo5-Jul-10 16:17 
    GeneralRe: Some unusual action and request solution Pin
    Herre Kuijpers6-Jul-10 3:14
    memberHerre Kuijpers6-Jul-10 3:14 
    GeneralRe: Some unusual action and request solution Pin
    Sports Kuo7-Jul-10 16:00
    memberSports Kuo7-Jul-10 16:00 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

    Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
    Web02 | 2.8.190306.1 | Last Updated 4 Jul 2007
    Article Copyright 2007 by Herre Kuijpers
    Everything else Copyright © CodeProject, 1999-2019
    Layout: fixed | fluid