Click here to Skip to main content
13,356,787 members (59,880 online)
Click here to Skip to main content
Add your own
alternative version


55 bookmarked
Posted 9 Nov 2005


, 9 Nov 2005
Rate this:
Please Sign up or sign in to vote.
CMagDialog: a class to enable dialogs to dock side by side.

Screenshot of demo application


I started to write this class because I'm often in need to popup additional dialogs around the main one. Often these dialogs can give some trouble to the user; for example, he must move/close them one by one... A solution that could give the application a more solid aspect and that could make the management of the various windows easier could be, to dock all dialogs side by side (like Winamp does, for example).


First of all: when I talk about parent dialog I mean the main dialog and the children are dialogs that can dock to the parent. I know that this isn't exactly the meaning that MS gives to these words but I can't think anything better ;) The class code is really simple. All my work was focused on two points: "the magnetic field" management that enables dialogs to dock, and avoid flickering when windows are forced to dock (i.e. you are inside the field ;)). The first point wasn't a real problem: my solution was to build around the parent dialog four rectangles (one for each side); if the center point of the correspondent child window's edge is inside the rectangle the child is docked.

Here is a snapshot of the code:

//m_pMagParentDlg: pointer to parent window
//pRect: pointer to child window rect
//m_dwMagType: Type of dock (left,right,top,bottom or any side...)


// Magnetic fields!
rectRight = CRect(rectParent.right-rHight,,
//Right magnetic field of parent dialog

curPl = CPoint(pRect->left, 
//center point of child's left edge

if ((m_dwMagType == DKDLG_RIGHT || m_dwMagType == DKDLG_ANY) && 

   nEdge        = DKDLG_RIGHT;    
   m_bDocked    = TRUE;

I spent some time to find a solution to the second problem (avoid flickering). I wanted to reproduce the same effect of Winamp dialogs: childrent that go inside the "magnetic field" of the parent will be pushed to dock. The code behind this effect is simple (a MoveWindow is enough...). The real problem is: where to put the code? Using the ON_WM_MOVING message is bad because this message is cast after the actual window movement so the resulting effect is really ugly (more than a simple flicker!). After some research, I found the right message to catch: ON_WM_WINDOWPOSCHANGING.

The prototype of this function is:

void CMagDialog::OnWindowPosChanging(WINDOWPOS* lpwndpos)

where lpwndpos is a structure that contain the coordinates to which the window will be moved. Filtering these coordinates according to my need is the trick.

void CMagDialog::OnWindowPosChanging(WINDOWPOS* lpwndpos)
    if ((m_bDocked) &  // This is a fix on movement... 
        (m_pMagParentDlg != NULL) &&
         // I need it only if the windows is docked
         // and I'm trying to move it:
        (m_bDisablePosFix == FALSE))
        // when this window is dragged
        // by parent window I don't need this fix
      CRect tmpRect,rectParent;
      if (nEdge == DKDLG_RIGHT)

    lpwndpos->x  = tmpRect.left;
    lpwndpos->y  =;
    lpwndpos->cx = tmpRect.Width();
    lpwndpos->cy = tmpRect.Height();

    //commit changes

Using the code

To use magnetic dialogs in your project, simply derive both the parent dialog and the children (see the Background section about the definition of parent and children) from the CMagDialog class. The children must be all modeless dialogs and should be defined inside the parent dialog class (the same thing happens when you are using dockable windows in a DOC/View architecture). Then you must call AddMagneticDialog and EnableMagnetic methods in the parent dialog for each child.

Let's say that m_MyMagDlg is a modeless dialog declared in theparent dialog class. The OnInitDialog will look like:

BOOL CCMagTestDlg::OnInitDialog()
   //this child will pop up docked on right side of parent window
   //and can dock to any side
   return TRUE;

As you can see in the demo, the class also remembers the relative position between the children and the parent so, if you close one child and move around the parent, when you will show the child again, it will placed in the same relative position that it had before.


These are the definitions of the two public methods of CMagDialog:

void AddMagneticDialog(CMagDialog* pDialog, 
         BOOL bDocked = FALSE,DWORD dwMagWhere =0);
  • PDialog - to child dialog.
  • bDocked - if true, the child window popup is already docked.
  • dwMagWhere - where the dialog docks; can have the following values:
void EnableMagnetic(DWORD dwMagType,CMagDialog* pMagParentDlg);
  • dwMagType - where the dialog can dock; values are the same as dwMagWhere described previously.
  • pMagParentDlg - pointer to the parent dialog window.


dwMagWhere refers to the parent's window side. So DKDLG_LEFT means that children will docked to the left side of the parent window.



  • First public release.


This program/code is free and provided "as is" without any expressed or implied warranty. Use at your own risk!


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


About the Author

Francesco Aruta
Italy Italy
No Biography provided

You may also be interested in...

Comments and Discussions

SuggestionConvert to template class Pin
Vachaun226-Jun-12 4:01
memberVachaun226-Jun-12 4:01 
GeneralRe: Convert to template class Pin
Francesco Aruta10-Jun-12 1:55
memberFrancesco Aruta10-Jun-12 1:55 
GeneralInteresting idea... Pin
Destiny77725-May-10 12:35
memberDestiny77725-May-10 12:35 
GeneralA small bug Pin
bluewater020923-Oct-06 17:48
memberbluewater020923-Oct-06 17:48 
GeneralRe: A small bug Pin
Francesco Aruta24-Oct-06 10:29
memberFrancesco Aruta24-Oct-06 10:29 
QuestionChild Dialogs? Pin
peterdrozd5-Oct-06 12:14
memberpeterdrozd5-Oct-06 12:14 
Generalthis way Pin
p3_1410-Feb-06 5:24
memberp3_1410-Feb-06 5:24 
GeneralDoes it work with VC 6.0 Pin
Varchas9-Jan-06 0:46
memberVarchas9-Jan-06 0:46 
GeneralRe: Does it work with VC 6.0 Pin
Francesco Aruta9-Jan-06 22:54
memberFrancesco Aruta9-Jan-06 22:54 
GeneralRe: Does it work with VC 6.0 Pin
kbomb9875-Apr-06 17:55
memberkbomb9875-Apr-06 17:55 
GeneralRe: Does it work with VC 6.0 Pin
Francesco Aruta6-Apr-06 12:52
memberFrancesco Aruta6-Apr-06 12:52 
kbomb987 wrote:
That works, cool class.

Thanks Smile | :)
By the way I suggest you this (that is more object oriented ) approach instead of my "quick and dirty" solution Wink | ;) .

kbomb987 wrote:
By the way, if you want to combine it with CResizingDialog, just change the base class of CMagDialog to CResizingDialog (and change the references of CDialog to CResizingDialog in the .cpp file) and now it resizes too.

This is another nice idea Smile | :)


TBEditor: a pandapowered app!

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 | Terms of Use | Mobile
Web03 | 2.8.180111.1 | Last Updated 9 Nov 2005
Article Copyright 2005 by Francesco Aruta
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid