Creating Dialog Resources and Instantiating Multiple Instances of a Dialog Box
In this code example a project was created in Visual Studio that is a Microsoft Foundation Classes (MFC)
application that is dialog based. The class ProjectNamedlg.cpp defines a dialog box
that is the main window for the application. Additional dialog boxes are created in the application
using dialog resources.
When the application is run a dialog box appears with three buttons on it. Clicking one button will
create and show a simple dialog box that displays a text message. Clicking the second button will
create and show a simple dialog box that displays a double value. Clicking the third button will
create and show a simple dialog box that displays a double value and shows the value in very simple
chart. You can click either button as
many times as you wish. DO NOT CLICK THE OK BUTTON ON ANY OF THE DIALOGS. To do so will
destroy the dialog and leave a dangling pointer in a vector.
Once every second a timer event will be passed to the application which will then iterate through
a vector of type 1 dialog boxes and change the message displayed in each, it will then iterate
through a vector of type 2 dialog boxes and change the value displayed in each, and finally it
will iterate through a vector of type 3 dialog boxes and change the value displayed in each.
To terminate the application click the Exit button on the main dialog box.
Creating the Dialog Based Project
-
Select File->New->Project and select MFC Application as shown (figure 1).
Figure 1
-
In the next dialog box, on the Application Type tab use the settings as shown (figure 2),
then click Finish
Figure 2
-
Visual Studio will create all of the files as shown in the listing below (figure 3). The file
named ProjectNameDlg.cpp is the class implementation file for the
main dialog box.
Figure 3
-
Look at the Resource View pane for the project. Locate the Dialog resource representing
the main dialog box (figure 4).
Figure 4
-
Double click the dialog resource to open it in the resource editor. Modify the
dialog resource (delete the cancel button, change the OK button to Exit, and
add three additional buttons as shown (figure 5).

Figure 5
You could at this point compile and run the application to see what it looks like.
Creating the Dialog Resources
-
Right click the resources folder in the project and select New->Resource (figure 6).

Figure 6
-
In the dialog box that pops up (figure 7) select Dialog in the list then click
the New button.

Figure 7
-
Use the resource editor to modify the new dialog resource so that it looks like the one
in figure 8.

Figure 8
-
Now create a second dialog resource and use the resource editor to modify it so that it
looks like the one in figure 9.

Figure 9
-
Now create a third dialog resource and use the resource editor to modify it so that it
looks like the one in figure 10.

Figure 10
Create classes to represent each of the dialog resources
-
Right click the main frame of a dialog resource in the resource editor view and select
add class from the popup menu (figure 10).

Figure 11
-
In the dialog box that appears (figure 11) provide a name for the class. In the
Dialog ID combobox field you should see the resource ID of the dialog
which will be used to create the on-screen dialog box that this class will be
associated with. Click Finish and the .h and .cpp files
will be created.

Figure 12
-
Look at the code listings below to see the code added to each of the .h
and .cpp files. The additions are enclosed in comments like this:
//------------------------------------------------
Code changes appear here...
//------------------------------------------------
Add code and event listeners to the main dialog class.
-
Open the main dialog in the resource editor. The easiest way to do this is
to locate the resource ID for the dialog in the resource view hierarchy tree
and double click it.
-
Double click each of the "add" buttons to add an event handler to the
ProjectNameDlg.cpp file.
-
Add two vectors to the ProjectNameDlg.h file. See the code listing
below. Don't forget to #include <vector>
-
Add the line afx_msg void OnTimer (UINT TimerVal); as shown in the
ProjectNameDlg.h file below. This defines the function that
a timer will call each time it is triggered.
-
In the ProjectNameDlg.cpp file (see below) you will add code in
six places:
-
Add #includes for the two dialog classes, math, and time.
-
Add the line ON_WM_TIMER (&CMultiDialogDemoDlg::OnTimer) between
BEGIN_MESSAGE_MAP and END_MESSAGE_MAP to capture timer events.
-
In the constructor call srand() to seed the random number generator and
call CWnd::SetTimer(1, 1000, 0); to create and set a timer. The arguments
are: 1 = an ID for this timer which you select, 1000 = number of milliseconds
between timer firings, 0 = NULL because we aren't specifying another function
to be called when the timer fires. We'll use the default OnTimer() function
from CDialog which we will override.
-
Add code in the OnBnClickedButton1 callback function for button 1
to create a dialog of type 1, set an initial message in it, show the
dialog, and finally add a pointer to the dialog to the vector of type 1 dialogs.
-
Add code in the OnBnClickedButton2 callback function for button 2
to create a dialog of type 2, set an initial value in it, show the
dialog, and finally add a pointer to the dialog to the vector of type 1 dialogs.
-
Add the code for the OnTimer() function.
See the code listing below for details.
Add code to the three other dialog classes.
-
In each of the dialog .h files (MultiDialog1.h, MultiDialog2.h, and MultiDialog3.h in this example
add the #include <string>. In the first dialog add the display() and
setMessage() functions and a string to hold the message to display in the
text box. In the second and third dialog add the display(), setData(), and getData()
functions and a double to hold the data.
-
In each of the dialog .cpp files add the function implementations as shown in the
code listings below.
Source listing for the MultiDialogDemoDlg.h class header file.
// MultiDialogDemoDlg.h : header file
//
#pragma once
//---------------------------------------------------
#include <vector>
#include "MultiDialog1.h"
#include "MultiDialog2.h"
#include "MultiDialog3.h"
using namespace std;
//---------------------------------------------------
// CMultiDialogDemoDlg dialog
class CMultiDialogDemoDlg : public CDialog
{
// Construction
public:
CMultiDialogDemoDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_MULTIDIALOGDEMO_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
//---------------------------------------------------
// These are the two event handler functions added
// when the buttons on the dialog were double clicked
// from the resource editor.
public:
afx_msg void OnBnClickedButton1();
afx_msg void OnBnClickedButton2();
afx_msg void OnBnClickedButton3();
// You must manually add the next line
afx_msg void OnTimer (UINT TimerVal);
// Vectors to hold pointers to each of the types of dialog boxes
private:
vector<MultiDialog1 *> m_vDialog1;
vector<MultiDialog2 *> m_vDialog2;
vector<MultiDialog3 *> m_vDialog3;
//---------------------------------------------------
};
Source listing for the MultiDialogDemoDlg.cpp class implementation file.
// MultiDialogDemoDlg.cpp : implementation file
//
#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include "MultiDialogDemo.h"
#include "MultiDialogDemoDlg.h"
//------------------------------------------------------
#include "MultiDialog1.h"
#include "MultiDialog2.h"
#include "MultiDialog3.h"
#include <math.h>
#include <time.h>
//------------------------------------------------------
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CMultiDialogDemoDlg dialog
CMultiDialogDemoDlg::CMultiDialogDemoDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMultiDialogDemoDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMultiDialogDemoDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CMultiDialogDemoDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_BUTTON1, &CMultiDialogDemoDlg::OnBnClickedButton1)
ON_BN_CLICKED(IDC_BUTTON2, &CMultiDialogDemoDlg::OnBnClickedButton2)
ON_BN_CLICKED(IDC_BUTTON3, &CMultiDialogDemoDlg::OnBnClickedButton3)
//------------------------------------------------------
// Add a catch for the timer event
ON_WM_TIMER (&CMultiDialogDemoDlg::OnTimer)
//------------------------------------------------------
END_MESSAGE_MAP()
// CMultiDialogDemoDlg message handlers
BOOL CMultiDialogDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
//------------------------------------------------------
srand((unsigned int)(time(NULL))); // Seed the random number generator
// Create a 1 second timer
CWnd::SetTimer(1, 1000, 0);
//------------------------------------------------------
return TRUE; // return TRUE unless you set the focus to a control
}
void CMultiDialogDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CMultiDialogDemoDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CMultiDialogDemoDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CMultiDialogDemoDlg::OnBnClickedButton1()
{
// TODO: Add your control notification handler code here
//------------------------------------------------------
MultiDialog1 *dlg = new MultiDialog1(); // Instantiate the class
dlg->Create(IDD_DIALOG1, NULL); // Create the dialog box
dlg->ShowWindow(SW_SHOWNORMAL); // Show it
string s = "Initial message"; // Create start message
dlg->setMessage(s); // Set an initial message value
dlg->display();
m_vDialog1.push_back(dlg); // Add it to the vector
//------------------------------------------------------
}
void CMultiDialogDemoDlg::OnBnClickedButton2()
{
// TODO: Add your control notification handler code here
//------------------------------------------------------
MultiDialog2 *dlg = new MultiDialog2(); // Instantiate the class
dlg->Create(IDD_DIALOG2, NULL); // Create the dialog box
dlg->ShowWindow(SW_SHOWNORMAL); // Show it
dlg->setData((double)(rand() % 100)); // Set an initial data value
dlg->display();
m_vDialog2.push_back(dlg); // Add it to the vector
//------------------------------------------------------
}
void CMultiDialogDemoDlg::OnBnClickedButton3()
{
//------------------------------------------------------
// TODO: Add your control notification handler code here
//------------------------------------------------------
MultiDialog3 *dlg = new MultiDialog3(); // Instantiate the class
dlg->Create(IDD_DIALOG3, NULL); // Create the dialog box
dlg->ShowWindow(SW_SHOWNORMAL); // Show it
// dlg->setData((double)(rand() % 100)); // Set an initial data value
// dlg->display();
m_vDialog3.push_back(dlg); // Add it to the vector
OnPaint();
}
//------------------------------------------------------
void CMultiDialogDemoDlg::OnTimer(UINT nIDEvent)
{
// Update the data in all of the dialog1 objects
for(vector<MultiDialog1 *>::iterator it=m_vDialog1.begin();
it != m_vDialog1.end(); it++)
{
// Create a random message
string msg = "Message - ";
char str[32];
int val = rand();
sprintf(str, "%d", val);
msg.append(str);
(*it)->setMessage(msg);
(*it)->display();
}
// Update the data in all of the dialog2 objects
for(vector<MultiDialog2 *>::iterator it=m_vDialog2.begin();
it != m_vDialog2.end(); it++)
{
// Decrement by 1.0 the data in each dialog2
// If it drops to 0 or below reset to another random value
double d = (*it)->getData();
if(d > 0.0) d-= 1.0;
if(d <= 0.0) d = (double)(rand() % 100);
(*it)->setData(d);
(*it)->display();
}
// Update the data in all of the dialog3 objects
for(vector<MultiDialog3 *>::iterator it=m_vDialog3.begin();
it != m_vDialog3.end(); it++)
{
// Decrement by 1.0 the data in each dialog3
// If it drops to 0 or below reset to another random value
double d = (*it)->getData();
if(d > 0.0) d-= 1.0;
if(d <= 0.0) d = (double)(rand() % 100);
(*it)->setData(d);
(*it)->display();
}
CDialog::OnTimer(nIDEvent); // Pass on to super
}
//------------------------------------------------------
Source listing for the MultiDialog1.h class header file.
#pragma once
//--------------------------------------------------------
#include <string>
using namespace std;
//--------------------------------------------------------
// MultiDialog1 dialog
class MultiDialog1 : public CDialog
{
DECLARE_DYNAMIC(MultiDialog1)
public:
MultiDialog1(CWnd* pParent = NULL); // standard constructor
virtual ~MultiDialog1();
//--------------------------------------------------------
// Display message function
void display();
void setMessage(string msg);
private:
string m_sMessage;;
//--------------------------------------------------------
// Dialog Data
enum { IDD = IDD_DIALOG1 };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
};
Source listing for the MultiDialog1.cpp class header file.
// MultiDialog1.cpp : implementation file
//
#include "stdafx.h"
#include "MultiDialogDemo.h"
#include "MultiDialog1.h"
// MultiDialog1 dialog
IMPLEMENT_DYNAMIC(MultiDialog1, CDialog)
MultiDialog1::MultiDialog1(CWnd* pParent /*=NULL*/)
: CDialog(MultiDialog1::IDD, pParent)
{
//------------------------------------------------------
m_sMessage = ""; // Initialize the string
//------------------------------------------------------
}
MultiDialog1::~MultiDialog1()
{
}
void MultiDialog1::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
//------------------------------------------------------
//-----------------------
// Show the message
//-----------------------
void MultiDialog1::display()
{
// Get the character array out of the string for the text field text.
this->GetDlgItem(IDC_EDIT1)->SetWindowTextA(m_sMessage.c_str());
}
//----------------------------
// Set the Message to display
//----------------------------
void MultiDialog1::setMessage(string msg)
{
this->m_sMessage.assign(msg);
}
//-----------------------------------------------------
BEGIN_MESSAGE_MAP(MultiDialog1, CDialog)
END_MESSAGE_MAP()
// MultiDialog1 message handlers
Source listing for the MultiDialog2.h class implementation file.
#pragma once
// MultiDialog2 dialog
//--------------------------------------------------------
#include <string>
using namespace std;
//--------------------------------------------------------
class MultiDialog2 : public CDialog
{
DECLARE_DYNAMIC(MultiDialog2)
public:
MultiDialog2(CWnd* pParent = NULL); // standard constructor
virtual ~MultiDialog2();
//--------------------------------------------------------
// Display data function
void display();
void setData(double data);
double getData();
private:
double m_dData;
//--------------------------------------------------------
// Dialog Data
enum { IDD = IDD_DIALOG2 };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
};
Source listing for the MultiDialog2.cpp class implementation file.
// MultiDialog2.cpp : implementation file
//
//-----------------------------------------------------------
#define _CRT_SECURE_NO_WARNINGS // Ignore K&R string warnings
#include "stdafx.h"
#include "MultiDialogDemo.h"
#include "MultiDialog2.h"
//-----------------------------------------------------------
// MultiDialog2 dialog
IMPLEMENT_DYNAMIC(MultiDialog2, CDialog)
MultiDialog2::MultiDialog2(CWnd* pParent /*=NULL*/)
: CDialog(MultiDialog2::IDD, pParent)
{
}
MultiDialog2::~MultiDialog2()
{
}
void MultiDialog2::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
//-----------------------------------------------------------
//--------------
// Show the data
//--------------
void MultiDialog2::display()
{
char dataStr[32];
sprintf(dataStr, "%.4f", m_dData); // Make a string
this->GetDlgItem(IDC_EDIT1)->SetWindowTextA(dataStr);
}
//--------------
// Set the data
//--------------
void MultiDialog2::setData(double data)
{
this->m_dData = data;
}
//--------------
// Get the data
//--------------
double MultiDialog2::getData()
{
return m_dData;
}
//-----------------------------------------------------------
BEGIN_MESSAGE_MAP(MultiDialog2, CDialog)
END_MESSAGE_MAP()
// MultiDialog2 message handlers
Source listing for the MultiDialog3.h class header file.
#pragma once
#include "afxwin.h"
// MultiDialog3 dialog
class MultiDialog3 : public CDialog
{
DECLARE_DYNAMIC(MultiDialog3)
public:
MultiDialog3(CWnd* pParent = NULL); // standard constructor
virtual ~MultiDialog3();
//--------------------------------------------------------
afx_msg void OnPaint();
// Display data function
void display();
void setData(double data);
double getData();
private:
double m_dData;
//--------------------------------------------------------
// Dialog Data
enum { IDD = IDD_DIALOG3 };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
DECLARE_MESSAGE_MAP()
public:
CEdit m_DataValueTextbox;
};
Source listing for the MultiDialog3.cpp class header file.
// MultiDialog3.cpp : implementation file
//
#include "stdafx.h"
#include "MultiDialogDemo.h"
#include "MultiDialog3.h"
// MultiDialog3 dialog
IMPLEMENT_DYNAMIC(MultiDialog3, CDialog)
MultiDialog3::MultiDialog3(CWnd* pParent /*=NULL*/)
: CDialog(MultiDialog3::IDD, pParent)
{
}
MultiDialog3::~MultiDialog3()
{
}
void MultiDialog3::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT1, m_DataValueTextbox);
}
BEGIN_MESSAGE_MAP(MultiDialog3, CDialog)
END_MESSAGE_MAP()
void MultiDialog3::OnPaint()
{
CDialog::OnPaint();
CDC *cdc = this->GetDC();
cdc->FillSolidRect(10, 30, 250, 50, RGB(255, 255, 255));
// m_dData value can be 0..100
// line X position is 2 * m_dData + 10 pixels to get into the solid rect
cdc->MoveTo(2*((int)(m_dData))+10, 30); // Draw line in the boundaries
cdc->LineTo(2*((int)(m_dData))+10, 80);
}
//-----------------------------------------------------------
//--------------
// Show the data
//--------------
void MultiDialog3::display()
{
char dataStr[32];
sprintf(dataStr, "%.4f", m_dData); // Make a string
this->GetDlgItem(IDC_EDIT1)->SetWindowTextA(dataStr);
OnPaint();
}
//--------------
// Set the data
//--------------
void MultiDialog3::setData(double data)
{
this->m_dData = data;
}
//--------------
// Get the data
//--------------
double MultiDialog3::getData()
{
return m_dData;
}
//-----------------------------------------------------------
The image below shows what the application looks like when running with one of each
dialog box type displayed.

Figure 13
To download a copy of the MultiDialogDemo program do the following:
-
Click on this Demo link to download a zip file
called MultiDialogDemo.
-
Unzip the archive file to find a single file called MultiDialogDemo.txt. The .exe
extension on the end was changed to .txt to avoid problems with some firewalls
when downloading zip files containing executables.
-
Change the .txt extension back to .exe.
-
Double click the executable to run the program.