Modeless child dialog in a Main Dialog with corrected tab order

This article was written to help the programmer put a modeless child dialog "into" another dialog and maintain the proper tab order for the new combination.

 

Normally when a modeless child dialog is created and placed in a parent dialog, the tab order follows the parent dialog. This is illustrated in the in the following picture. The first tab item (5) of the child dialog follows the last tab item of the parent (4)

 

What we would like to have is the first child tab item following the control of choice in the main dialog:

 

To perform this feat is fairly simple but if you dont know how to do it you may spend quite a few hours coding pretranslate messages and setting focus to controls.

 

Step 1: Create the Main dialog and the child dialog using the dialog editor. Create classes for the dialogs using the class wizard. Then change some properties of the child dialog:

The child dialog will have the "child dialog" and the "control" style. Note: I have set the border to thin, but in this example the border will not show up because of the control style.

Using the dialog editors properties dialog, set the CHILD dialog styles as follows:

 

You will also have click on the More Styles tab and set the "control" style:

 

To make the child dialog show up exactly where is designed to show up on the main dialog, the X,Y locations in the general tab can be set. The child dialog will show up in this application at X = 23 and Y = 36.

 

 

Step 2:

The program will compile now and it will run, but the child dialog will not show up on the main dialog. You will have to place an instance of the child dialog in the main dialog class. Include the header file for the child dialogs class and create a member variable for the child dialog:

#include "ChildDialog.h"

class CDlgSampleDlg : public CDialog
{
   CChildDialog m_child;

 

Since the child dialog will need a CWnd pointer in the constructor you will have to place the m_child variable in the constructor for the main dialog.

CDlgSampleDlg::CDlgSampleDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CDlgSampleDlg::IDD, pParent),
	m_child( this )
{
	// Dialog constructor code
}

The next coding you will perform is a call to Create via the child dialog member variable in the OnInitDialog function of the main dialog. Dont forget to show the window after you create the child dialog

BOOL CDlgSampleDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

   m_child.Create( IDD_CHILD_DIALOG, this );
   m_child.ShowWindow( TRUE );

 

At this point the project should compile and run. However the tab order will not be what we originally set out to correct. To fix the tab order the following code will have to be inserted at the end of the OnInitDialog function:

	// TODO: Add extra initialization here

   CWnd * pWnd = GetDlgItem( IDC_CONTROL_1 );
   UINT nFlags = SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE;

   ::SetWindowPos( m_child.m_hWnd, pWnd->m_hWnd, 0, 0, 0, 0, nFlags );
   return TRUE;
}

 

The ID "IDC_CONTROL_1" is the control in the main dialog that will be just before the first tab order item in the child dialog.

 

Compile the program, run it and tab through the controls the child dialogs controls will follow the correct tabbing order as expected.

Download demo project - 5 KB

Download source - 12 KB