Enhacing CDialogBar with InitDialog and DDX

As you all know, the CDialogBar control, is the MFC control that lets the programmer add any control he wants, into a dockable window via a dialog template. This class is very much like the CDialog class iteself; however, there are two major differences between the classes.
CDialogBar does not have an OnInitDialog function where you can initialize your controls, nor does it support the DDX mechanism. These are two simple items which can be added to a new class, thereby making it possible to have a CDialogBar that behaves much more like a regular CDialog.
As it turns out, a class that does this is quite simple to implement. The support for DDX is already built into CWnd, the base class of CDialogBar. The required DDX_??? Functions to update the controls are global MFC functions and CWnd already supports the DDX mechanism. Why DDX support never found itself into the MFC CDialogBar is really puzzling? To add it all you need to do is call the already provided functions at the proper time. By taking these few simple steps, you then create a powerful, yet simple class that really makes getting the data from your CDialogBar controls much eaiser. Below I will outline the steps to creating the CInitDialogBar class.
The first step is to look at where CDialog initializes the DDX mechanism. It does so in its OnInitDialog function, with its first call to UpdateData(). This function is a CWnd function, not a CDialog function. Since CDialogBar has no OnInitDialog() function, we need to mimic this behavior with our derived CDialogBar class. In CDialog, OnInitDialog() gets called in response to the dialog window sending itself a WM_INITDIALOG message. CDialogBar has no such message since its really a CWnd and not strictly a dialog window. The important thing to note, is that the WM_INITDIALOG message, in a real dialog, is sent to the window after its handle exists. This means that although we won’t officially send ourselves a message in the CInitDialogBar class, that we can call our own version of OnInitDialog() after the handle to our window exists. We modify the create function of CDialogBar to do this. Since Create() for a CDialogBar is overloaded we redefine each create and make out modifications to it.

First in the CInitDialogBar class redefine the public create functions:

BOOL Create(CWnd * pParentWnd, UINT nIDTemplate, UINT nStyle, UINT nID);

BOOL Create(CWnd * pParentWnd, LPCTSTR lpszTemplateName, UINT nStyle, UINT nID);
By doing this, we don’t change the way our CInitDialogBar is created.

Next, define a virtual function, which all derived classes will override. This function, will provide the missing OnInitDialog() functionality. Also we re-declare the virtual CWnd DDX funtion DoDataExchange as well:
virtual BOOL OnInitDialogBar();

// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CInitDialogBar)
protected:
virtual void DoDataExchange(CDataExchange* pDX);
//}}AFX_VIRTUAL
We are now ready to implement our new functions. Let’s start with the Create(). CDialogBar already has a Create() which will create the control for us. Let’s not reinvent the wheel, but instead reuse it. (Both overloaded functions are changed in the same way so I will only show one here.) After we call the base class, Create() function our m_hWnd is valid. This is what we have been waiting for. We can now call our OnInitDialogBar() function.
// Let MFC Create the control
// Call the base class Create()
if(!CDialogBar::Create(pParentWnd,
	lpszTemplateName, /*(nIDTemplate) for other Create()*
	nStyle, nID))
{
	return FALSE;
}

// Since there is no WM_INITDIALOG message we have to call
// our own InitDialog function ourselves after m_hWnd is valid
if(!OnInitDialogBar())
	return FALSE;
return TRUE;
Just like in CDialog the OnInitDialogBar() will initialize the DDX mechanism for us by calling The UpdateData() function. For this reason it will be important for derived classes to call the base class. The UpdateData() function will call our virtual DoDataExchange(), for now we will leave this function blank. We will put our initializing code in our derived classes. That’s pretty much all the new code we need. We are now ready to start using our class and deriving our own objects from it.
The first step is to derive your own object from CInitDialogBar. To create the Dialog bar in our CMainFrame object do the following in the CMainFrame::OnCreate():
// CInitDialogBar m_wndDialogBar; in mainframe.h

if (!m_wndDialogBar.Create(this, IDD_DBAR, CBRS_LEFT, 0))
{
	TRACE0("Failed to create InitDialogBar\n");
	return -1; // fail to create
}

m_wndDialogBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndDialogBar);
At this point, a dialog bar should appear with the template that you provide for it. The controls don’t communicate with the CInitDialogBar derived object; let’s remedy this. Because of the way CInitDialogBar was written we now only need to override our two virtual functions. Below are the functions and the required code to initialize a CBitmapButton and CheckBox.
BOOL CMainDialogBar::OnInitDialogBar()
{
	// Support for DDX mechanism
	// If you do not want DDX then
	// do not call base class
	// All out DDX controls are intialized
	// the virtual call to DoDataExchange.
	CInitDialogBar::OnInitDialogBar();

	// Initialize any controls NOT supported by DDX
	// CBitmapButton is one
	m_OKButton.AutoLoad(IDOK, this);

	return TRUE;
}

void CMainDialogBar::DoDataExchange(CDataExchange* pDX)
{
	ASSERT(pDX);

	CInitDialogBar::DoDataExchange(pDX);

	// DDX_??? functions to synchronize control with
	// data or control object

	//{{AFX_DATA_MAP(CAboutDlg)
	DDX_Check(pDX, IDC_CHECK1, m_CheckBox);
	//}}AFX_DATA_MAP
}
We now have a CDialogBar that uses the DDX mechanism. This makes it much easier to keep out controls and their variables synchronized. Any time you want the current state of your DDX controls just call UpdateData(TRUE). This will synchronize the variables with the controls current state. And likewise to set the controls to a know state call UpdateData(FALSE).

The complete code for CInitDialogBar and a sample derived object follow.

Enjoy! :)
//////////////////////////////////////////////////////////////////////
//
// InitDialogBar.h: interface for the CInitDialogBar class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_INITDIALOGBAR_H__46B4D2B3_C982_11D1_8902_0060979C2EFD__INCLUDED_)

#define AFX_INITDIALOGBAR_H__46B4D2B3_C982_11D1_8902_0060979C2EFD__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

////////////////////////////////////////////////////////////////////////////
//
// CInitDialogBar window
//
////////////////////////////////////////////////////////////////////////////

class CInitDialogBar : public CDialogBar
{
	DECLARE_DYNAMIC(CInitDialogBar)

	// Construction / Destruction
	public:
	CInitDialogBar();
	virtual ~CInitDialogBar();

	// Attributes
	public:

	// Operations
	public:

	// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CInitDialogBar)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);
	//}}AFX_VIRTUAL

	// Implementation
	public:
	BOOL Create(CWnd * pParentWnd, UINT nIDTemplate, UINT nStyle, UINT
	nID);
	BOOL Create(CWnd * pParentWnd, LPCTSTR lpszTemplateName, UINT
	nStyle, UINT nID);

	protected:
	virtual BOOL OnInitDialogBar();

	// Generated message map functions
	protected:
	//{{AFX_MSG(CInitDialogBar)
	// NOTE - the ClassWizard will add and remove member functions
	here.
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

////////////////////////////////////////////////////////////////////////////
/

#endif // !defined(AFX_INITDIALOGBAR_H__46B4D2B3_C982_11D1_8902_0060979C2EFD__INCLUDED_)

////////////////////////////////////////////////////////////////////////////
//
// InitDialogBar.cpp: implementation of the CInitDialogBar class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "spectra.h"
#include "InitDialogBar.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNAMIC(CInitDialogBar, CDialogBar)

BEGIN_MESSAGE_MAP(CInitDialogBar, CDialogBar)
//{{AFX_MSG_MAP(CInitDialogBar)
// NOTE - the ClassWizard will add and remove mapping macros
here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

CInitDialogBar::CInitDialogBar()
{
	// In derived classes set intial
	// state of control(s) here
}

CInitDialogBar::~CInitDialogBar()
{

}

BOOL CInitDialogBar::Create(CWnd * pParentWnd, LPCTSTR lpszTemplateName,
	UINT nStyle, UINT nID)
{
	// Let MFC Create the control
	if(!CDialogBar::Create(pParentWnd, lpszTemplateName, nStyle, nID))
		return FALSE;

	// Since there is no WM_INITDIALOG message we have to call
	// our own InitDialog function ourselves after m_hWnd is valid
	if(!OnInitDialogBar())
		return FALSE;

	return TRUE;
}

BOOL CInitDialogBar::Create(CWnd * pParentWnd, UINT nIDTemplate,
	UINT nStyle, UINT nID)
{
	if(!Create(pParentWnd, MAKEINTRESOURCE(nIDTemplate), nStyle, nID))
		return FALSE;

	// Since there is no WM_INITDIALOG message we have to call
	// our own InitDialog function ourselves after m_hWnd is valid
	if(!OnInitDialogBar())
		return FALSE;
	return TRUE;
}

BOOL CInitDialogBar::OnInitDialogBar()
{
	// Support for the MFC DDX model 
	// If you do not want this do not call the base class
	// from derived classes
	UpdateData(FALSE);

	return TRUE;
}

void CInitDialogBar::DoDataExchange(CDataExchange* pDX)
{
	//Derived Classes Overide this function
	ASSERT(pDX);

	CDialogBar::DoDataExchange(pDX);

	// In derived class call the DDX_??? functions to set/retrieve values
	// of your controls. See example derived class for how to do this.
}

Sample derived Control:
//////////////////////////////////////////////////////////////////////
//
// MainDialogBar.h: interface for the CMainDialogBar class.
//
//////////////////////////////////////////////////////////////////////


#if !defined(AFX_MAINDIALOGBAR_H__46B4D2B3_C982_11D1_8902_0060979C2EFD__INCLUDED_)

#define AFX_MAINDIALOGBAR_H__46B4D2B3_C982_11D1_8902_0060979C2EFD__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

#include "InitDialogBar.h"

// CMainDialogBar window

class CMainDialogBar : public CInitDialogBar
{
	DECLARE_DYNAMIC(CMainDialogBar)

	// Construction
	public:
	CMainDialogBar();
	virtual ~CMainDialogBar();

	// Attributes
	public:
	protected:

	// Control Objects
	CBitmapButton m_OKButton;

	// Control Variables
	BOOL m_CheckBox;

	// Operations
	public:

	// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CMainDialogBar)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);
	//}}AFX_VIRTUAL

	protected:
	virtual BOOL OnInitDialogBar();

	// Implementation
	public:

	// Generated message map functions
	protected:
	//{{AFX_MSG(CMainDialogBar)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

////////////////////////////////////////////////////////////////////////////
/

#endif // !defined(AFX_MAINDIALOGBAR_H__46B4D2B3_C982_11D1_8902_0060979C2EFD__INCLUDED_)

////////////////////////////////////////////////////////////////////////////
//
// MainDialogBar.cpp: implementation of the CMainDialogBar class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "spectra.h"
#include "MainDialogBar.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNAMIC(CMainDialogBar, CInitDialogBar)

BEGIN_MESSAGE_MAP(CMainDialogBar, CInitDialogBar)
//{{AFX_MSG_MAP(CMainDialogBar)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


CMainDialogBar::CMainDialogBar()
{
	//Set Initial conditions for controls
	m_CheckBox = 1;
}


CMainDialogBar::~CMainDialogBar()
{

}


BOOL CMainDialogBar::OnInitDialogBar()
{
	// Support for DDX mechanism
	// If you do not want DDX then
	// do not call base class
	CInitDialogBar::OnInitDialogBar();

	// Update any controls NOT supported by DDX
	// CBitmapButton is one
	m_OKButtton.AutoLoad(IDOK, this);

	return TRUE;
}

void CMainDialogBar::DoDataExchange(CDataExchange* pDX)
{
	ASSERT(pDX);

	CInitDialogBar::DoDataExchange(pDX);

	// DDX_??? functions to associate control with
	// data or control object
	// Call UpdateData(TRUE) to get data at any time
	// Call UpdateData(FALSE) to set data at any time

	//{{AFX_DATA_MAP(CAboutDlg)
	DDX_Check(pDX, IDC_CHECK1, m_CheckBox);
	//}}AFX_DATA_MAP
}

Last updated: 11 May 1998



Comments

  • where you can procure the cheapest clarisonic mia

    Posted by iouwanzi on 06/06/2013 09:12pm

    [url=http://www.miaclarisonicaustralia.org/]clarisonic mia online[/url] Victoria Secret 2012, la dernière conférence de maillots de bain sur la belle Miranda Kerr trésor et sexy top model Candice Swanepoel lors de la sélection se tailler un style de grands ghd lisseur cheveux de milliers de féminité sexy. Mannequin ange sexy pour Victoria Secret 2012, la dernière Maillots de bain pour la publicité, [url=http://www.miaclarisonicaustralia.org/clarisonic-classic]clarisonic classic[/url] Sur la photo précédemment mentionné, la chose est qu’il y a exclusivement un interrupteur marche/arrêt. Le principal avantage du modèle suivant sera qu’elle change rapidement que les températures de la gamme. Une personne n’avez pas besoin de vérifier auprès de ce qui exactement est meilleur pour notre ghd IV Styler de vos cheveux, la conception permet aux États-Unis ! La température moyenne autour de chaque ghd IV Styler est située à 180 ° d. Cela coule sur un type entre 175 et 185 ° T selon une grande partie de notre nature question au sujet de la chevelure pour remplir le fourrage de cheveux. [url=http://www.miaclarisonicaustralia.org/clarisonic-mia]clarisonic mia[/url] peut-être mieux si vous profitez de cette fondation se bloque style pour le monde moderne. devenir une personne mystifié destinée à une bonne approche très bon pour faire la coiffure impressionnante? vous permet de le fait que c’est dans la terre soigneusement introduire une règle peut être limitée par un excellent instrument qui est connecté n’est pas vraiment efficace appréciation des résultats définitifs de ces cheveux crépus? et peut également demander le jaune est toujours dans vos propres besoins redressement de vos cheveux. Rose tout simplement charmant, le moment, en raison de la longue durée développer la gestion motif merveilleux et très important. En outre, ghd lisseur en céramique infrarouge critique couvre belle chevelure bouclée, et également la compression d’huiles naturelles, de l’eau et de serrures colorants alimentaires, bouclés cheveux sauvages éclatantes assurés reçoivent des produits de qualité supérieure qui va venir.

    Reply
  • Here's A Technique That Is In fact Aiding gucci-professionals To Improve

    Posted by BobHotgloff on 05/03/2013 05:23am

    Quick blog post instructs you all the intricacies on mizuno and the things you ought to do this afternoon. [url=http://www.mizunogoruhujp.com/]ミズノ[/url] The Secret For mizuno [url=http://www.mizunogoruhujp.com/ミズノ-ゴルフクラブ-c-1.html]ミズノ グラブ[/url] Brief article explains most of the intricacies on nike coupled with precisely what you want to execute straight away. [url=http://www.mizunogoruhujp.com/ゴルフグローブ-c-33.html]ミズノ グローブ[/url] What everybody else engages in in the matter of mizuno and consequently those things you'd probably like to perform completely different. [url=http://www.mizunogoruhujp.com/ゴルフバッグ-c-7.html]ミズノゴルフ[/url] Third party website provides Some innovative new things about nike that none is bringing up. [url=http://www.mizunogoruhu.com/]ミズノ グローブ[/url] A powerful solid double take on nike [url=http://www.mizunogoruhu.com/ミズノmizuno-クラブ-c-4.html]ミズノ グラブ[/url] Accessories and performance throughout Michigan -- nike has left with no good bye [url=http://www.mizunogoruhu.com/ミズノmizuno-アイアン-c-3.html]ミズノ[/url] Robust advise for mizuno which you can use commencing now. [url=http://www.mizunogoruhu.com/ミズノmizuno-バッグ-c-5.html]ミズノゴルフ[/url] Brief document discloses the unignorable info regarding nike as well as how it can affect anyone.

    Reply
  • thanks!

    Posted by Legacy on 11/10/2003 12:00am

    Originally posted by: JasonH

    I had never used dialog bars before and trying to access the controls on one was driving me crazy. Good article.

    Reply
  • Thank you very very much

    Posted by Legacy on 10/17/2003 12:00am

    Originally posted by: Edward King

    CDialogBar was driving me mad because I couldn't initialise my spin controls, but now thanks to you I can. Thank you.

    Reply
  • Keyboard events into a CEdit an CDialogBar

    Posted by Legacy on 09/27/2003 12:00am

    Originally posted by: Roberto

    I/m trying to do a navigator in visual c++. I have a CEdit in a CDialogBar and i want to navigate throw the address in the edit control when the user push intro into the component, but i cannot get de WM_CHAR message, nor the WM_KEYDOWN, nor the WM_KEYUP. The program doesn't responds these message anywhere i write the code for the asociated funcions.

    Reply
  • CTRL + C and CTRL + V does not work

    Posted by Legacy on 09/26/2003 12:00am

    Originally posted by: Sandeep Naik

    I have used DialogBar and dropped a combo box on it. I have put it on ReBar Control. Now on the ComboBox Ctrl+c and Ctrl+v doesn't work. But I can right mouse click and say copy/paste.
    Any body knows how to enable these

    • How to make keyboard event work in CDialogBar derived class

      Posted by hemant_jangid on 10/24/2005 03:19am

      Answer to this question and all other questions like Ctrl+C, Ctrl+X keys not working, tab key not moving focus etc. lies in the heart of every window object i.e. message pump.
      Short answer: Because modeless dialogs and Dialogbar classes donbt provide the pre-translation of dialog keys.
      
      Long answer: For implementation of keyboard accelerators, special behavior in dialogs require pre-translation of windows messages. For example, ctrl+x for ID_FILE_CUT and ctrl+v ID_FILE_PASTE.
      
      Modal dialog class CDialog have a virtual function PreTranslateMessage which takes care of special dialog related keys. Root of all problems is that CDialogBar class doesnbt provide this functionality. To make it work, all we have to override above function in CDialogBar derived class. Following function addition can solve this problem for CDialogBarEx class.
      
      // In CDialogBarEx.h
      virtual BOOL PreTranslateMessage(MSG* pMsg);
      
      
      // In CDialogBarEx.cpp
      BOOL CDialogBarEx::PreTranslateMessage(MSG* pMsg)
      {
      	if (pMsg->message >= WM_KEYFIRST && // for performance
      		pMsg->message <= WM_KEYLAST)
      	{
      		// Translate dialog key if applicable
      		if(::IsDialogMessage(m_hWnd, pMsg))
      			return TRUE;
      	}
      
      	return CDialogBar::PreTranslateMessage(pMsg);
      }
      
      Solution to this problem and many other windows message related problems can be found at following link:
      
      http://www.microsoft.com/msj/0795/dilascia/dilascia.aspx
      
      I have got present solution also from this article. It is really an excellent article about MFC message handling and routing.
      
      Cheers,
      Hemant Jangid

      • thx

        Posted by god4 on 12/13/2013 12:12am

        very well, thank you very much.

        Reply
      Reply
    Reply
  • Tree Controls not redrawing?

    Posted by Legacy on 08/16/2003 12:00am

    Originally posted by: Adam Clauss

    I have begun using this class and I have noticed that tree controls do not redraw properly. NOTHING appears until I click on it - and then when I do, only certain items appear... if I drag the window off screen and drag it back, EVERYTHING disappears again. I'm using the dialog bar as part of an MDI app. Any ideas?

    Reply
  • Thankyou!!!!!!!!!!!!!!!!

    Posted by Legacy on 06/04/2003 12:00am

    Originally posted by: Stevebob

    This problem has been driving me crazy all day and your tutorial cleared the problem right up. Thanks!

    Reply
  • Event for CDialogBar Docking & Floating

    Posted by Legacy on 07/25/2002 12:00am

    Originally posted by: Dave

    Hi there,
    Can u pls tell me the events to be trapped to know when a CDialogBar is 1]Docking and 2]Floating?
    I need to resize my frame programatically, whenever the dialog bar is docked and floated and docked back.
    Thankx Very much
    Dave :)

    Reply
  • How to display tooltips.

    Posted by Legacy on 03/16/2002 12:00am

    Originally posted by: Jos� Leandro Massada

    // define the tooltip control
    
    CToolTipCtrl m_tooltip;

    // initiate the tooltip control
    BOOL CMyDialogBar::OnInitDialogBar()
    {
    ...
    m_tooltip.Create(this);
    m_tooltip.Activate(TRUE);
    m_tooltip.AddTool(GetDlgItem(IDOK), "This is IDOK");
    ...
    }

    // implement RelayEvent() to make the tooltips work
    BOOL CDlgBar::PreTranslateMessage(MSG* pMsg)
    {
    m_tooltip.RelayEvent(pMsg);
    return CDialogBar::PreTranslateMessage(pMsg);
    }

    // regards :)

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • According to a recent Forrester total economic impact (TEI) study, enterprises can see a significant reduction in total cost of ownership by accessing Oracle Database in the cloud with a pay-as-you-go subscription model. This subscription service gives businesses the ability to scale up application environments for rapid prototyping, with far less time devoted to procuring licenses and deploying IT infrastructure. Read this study to learn how three different companies use Oracle Database in the cloud and the …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds