Click here to Skip to main content
13,292,205 members (63,518 online)
Click here to Skip to main content
Add your own
alternative version


43 bookmarked
Posted 15 Oct 2001

Creating a Dialog-based App

, 15 Oct 2001
Rate this:
Please Sign up or sign in to vote.
This is my method of creating dialog-based apps, and in addition, illustrates how to handle the Enter key in an edit control.


There are a large number of recurring questions on creating dialog-based apps. This is my method of creating dialog-based apps, and in addition, illustrates how to handle the Enter key in an edit control.

The most common problems people ask about are "How do I trap the ESC key so it doesn't terminate my application?" and "How do I trap the Enter key so it doesn't terminate my application?". These are easy.

First, I do not believe in handling this in PreTranslateMessage. The result of this is distributed knowledge which makes it difficult to maintain the code, particularly when controls are added or deleted. My technique uses subclassing to put the intelligence where it belongs, in the control, and puts the handlers in a known and easily understood place, a message handler.

First, create your dialog-based application. You will end up with something that resembles the dialog below (which I've shrunk so it doesn't take up too much space on the page):

Enter the ClassWizard. Select IDOK and its BN_CLICKED handler, and click Add Function. Accept the name it gives. Do the same for IDCANCEL. You should end up with something that looks like the illustration shown below. I show the IDCANCEL handler clicked, since that is the last one I added (note that two lines below, the ON_IDOK::BN_CLICKED handler is already present).

Next, select the dialog class, and find the WM_CLOSE message handler. Click Add Function. You should now have something like I show below:

Go to your source code and examine it. You can either exit ClassWizard via the OK button, or click the Edit Code button. Your code should look like this:

void CDialogappDlg::OnOK() 
    // TODO: Add extra validation here


void CDialogappDlg::OnCancel() 
    // TODO: Add extra cleanup here

void CDialogappDlg::OnClose() 
    // TODO: Add your message handler code here and/or call default


Change it to be as shown below. Delete the bodies of OnOK and OnCancel. Put the CDialog::OnOK call in the OnClose handler.

void CDialogappDlg::OnOK() 

void CDialogappDlg::OnCancel() 

void CDialogappDlg::OnClose() 

Go back to the dialog. Delete the OK and Cancel buttons. Add in your controls. For example, I want to add an edit control that reacts only when you either leave it or hit Enter, and prior to that it can be changed without any effect. The other control reacts immediately.

To create an edit control that reacts immediately, put in an EN_CHANGE handler.

Also, create a member variable for the control; I describe how to do this in a companion essay.

In order to access the status control which will show the effect, you must assign it an ID other than IDC_STATIC. Create a control variable to represent it.

I end up with variables as shown below (note that I have not yet created a variable for IDC_DELAYED):

The code for immediate response is simple:

void CDialogappDlg::OnChangeImmediate() 
 CString s;

When running, it produces output such as:

As each character is typed in the "Immediate Reaction" edit control, it appears in the box labeled "I see".

However, I might not want a reaction to take place until I hit Enter, or leave focus, or both. To do this, I create a subclass of CEdit:

Create a class derived from CEdit, which I have called CEnterEdit.

Now create a member variable for IDC_DELAYED of that type:

Which should leave you with the following definitions:

Notifying the Parent

In ClassWizard, select the new class you defined. (Note that if you are continuing from the previous step, you will be prompted to save your changes; select "Yes").


You must remember to add the header file for your new class to your compilations before any file that uses it. For a dialog-based app, this means the app source and the dialog source must both have it, for example:

#include "stdafx.h"
#include "dialogapp.h"
#include "EnterEdit.h"
#include "dialogappDlg.h"

Otherwise, you will get compilation errors whenever your ...Dlg.h file is processed.

If you use a custom message, you must define it. I prefer to use Registered Window Messages, as outlined in my companion essay, so I added to EnterEdit.h the following declaration. Note that it is critical that when you add a user-defined message, you document its parameters, effect and return result! Doing anything less will lead to unintelligible and unmaintainable code.

*                              UWM_EDIT_COMPLETE
* Inputs:
*       WPARAM: Control ID of the control whose edit completed
*    LPARAM: CWnd * of the control whose edit completed
* Result: LRESULT
*       Logically void, 0, always
* Effect: 
*       Posted/Sent to the parent of this control to indicate that the
*    edit has completed, either by the user typing <Enter> or focus leaving


I declare it in EnterEdit.cpp as shown below, or you could use the more convenient DECLARE_MESSAGE macro I defined in my companion essay.


This allows me to write the handlers I need.

First, in order to bypass the tendency of the dialog superclass to intercept and handle keyboard input, you should make the indicated change in the OnGetDlgCode handler:

UINT CEnterEdit::OnGetDlgCode() 
    return CEdit::OnGetDlgCode() | DLGC_WANTALLKEYS;

This tells the dialog superclass that when focus is in this control, it should deliver to it all the keys pressed.

Then, in your OnChar handler, you can do

void CEnterEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
      { /* nChar */
       case VK_RETURN:
                             GetDlgCtrlID(), (LPARAM)this);
      } /* nChar */
  CEdit::OnChar(nChar, nRepCnt, nFlags);

Why a switch with only one case? Why not? It makes it easy to add other cases, and captures the fact that you are concerned at the moment with some finite set of characters. I prefer switch statements in such contexts. They eliminate the temptation to add complex if-then-else structures, resulting in cleaner and easier-to-maintain code.

When an Enter key is seen, the message is sent to the parent which can then react to it.

To handle processing when focus is lost, modify the reflected =EN_KILLFOCUS handler as shown below:

void CEnterEdit::OnKillfocus() 
 GetParent()->SendMessage(UWM_EDIT_COMPLETE, GetDlgCtrlID(), (LPARAM)this);

Now you need to add a handler to the parent. This means you must declare a UINT for the Registered Window Message just like you did in the child edit control, and add the indicated message to the MESSAGE_MAP:

BEGIN_MESSAGE_MAP(CDialogappDlg, CDialog)
    ON_EN_CHANGE(IDC_IMMEDIATE, OnChangeImmediate)

IMPORTANT: This should be outside (above or below; I show above) the magic AFX_MSG_MAP comments! Otherwise you can confuse the ClassWizard.

You must add a handler to the declarations in your header file:

    afx_msg LRESULT OnEditComplete(WPARAM, LPARAM);
// Generated message map functions
virtual BOOL OnInitDialog();

IMPORTANT: This must be outside (above or below, I show above) the magic AFX_MSG comments. Otherwise you can confuse the ClassWizard.

The handler could look like the one I show here:

LRESULT CDialogappDlg::OnEditComplete(WPARAM, LPARAM lParam)
     CEnterEdit * edit = (CEnterEdit *)lParam;
     CString s;
     return 0;
    } // CDialogappDlg::OnEditComplete

In this simple example, I don't care which window generated the message, so I ignore WPARAM, and whatever control was activated, I simply set its text into the status window. In a dialog with many controls, you would probably want to switch on the WPARAM value.

Now when I run the app, and type text into the "Delayed Reaction" box, I see the following. Note that the contents of the "I see" status box is whatever was left from the previous typing.

But if I hit Enter or change focus, I will get the following result. The new text is in the "I See" box, and the focus (as shown by the caret) is still in the "Delayed Reaction" box.

Or, if I switch focus, I will also see the effect. Note that by doing this on a kill focus, I will also see the text activate if I switch to another application. If this is not desired, don't use the =EN_KILLFOCUS reflector, or you must do a more complex test. Note that starting from the first picture, I get the result shown below when I change focus to the upper window.


Many people have commented on this technique, "You are creating another subclass. Why do you feel you need to do this?" Never be afraid to create a custom subclass. I have been known to create a dozen in one day. It is a natural paradigm for MFC programming. These are the techniques I use to build real software that is used by thousands of people and maintained by someone other than myself.

The views expressed in these essays are those of the author, and in no way represent, nor are they endorsed by, Microsoft.

Send mail to with questions or comments about this article.
Copyright © 1999 All Rights Reserved


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Joseph M. Newcomer
United States United States
PhD, Computer Science, Carnegie Mellon University, 1975
Certificate in Forensic Science and the Law, Duquesne University, 2008

Co-Author, [i]Win32 Programming[/i]

You may also be interested in...


Comments and Discussions

AnswerRe: How to set Dialog ontop Pin
Joseph M. Newcomer16-Dec-02 16:36
memberJoseph M. Newcomer16-Dec-02 16:36 
GeneralRe: How to set Dialog ontop Pin
Joseph M. Newcomer16-Dec-02 19:31
memberJoseph M. Newcomer16-Dec-02 19:31 
GeneralIs there a way to find all the modal dialog boxes open within an application Pin
Hawkeye10-Sep-02 11:09
memberHawkeye10-Sep-02 11:09 
GeneralRe: Is there a way to find all the modal dialog boxes open within an application Pin
Joseph M. Newcomer17-Sep-02 8:10
memberJoseph M. Newcomer17-Sep-02 8:10 
GeneralRe: Is there a way to find all the modal dialog boxes open within an application Pin
Hawkeye19-Sep-02 10:38
memberHawkeye19-Sep-02 10:38 
QuestionHow to stop child dialogs from overlaping the parent Dlg Pin
Hawkeye7-Jun-02 14:36
memberHawkeye7-Jun-02 14:36 
AnswerRe: How to stop child dialogs from overlaping the parent Dlg Pin
Joseph M. Newcomer11-Jun-02 4:08
memberJoseph M. Newcomer11-Jun-02 4:08 
AnswerRe: How to stop child dialogs from overlaping the parent Dlg Pin
Omee4u16-Aug-02 8:34
memberOmee4u16-Aug-02 8:34 
GeneralThis technique does not work with combo boxes Pin
Marcus Carey24-Mar-02 13:02
memberMarcus Carey24-Mar-02 13:02 
GeneralRe: This technique does not work with combo boxes Pin
Joseph M. Newcomer29-Mar-02 3:31
memberJoseph M. Newcomer29-Mar-02 3:31 
GeneralProblem on destroying a modal dialog box Pin
bogdan_rechi7-Mar-02 22:52
memberbogdan_rechi7-Mar-02 22:52 
GeneralRe: Problem on destroying a modal dialog box Pin
Joseph M. Newcomer8-Mar-02 6:45
memberJoseph M. Newcomer8-Mar-02 6:45 
GeneralRe: Problem on destroying a modal dialog box Pin
Nish [BusterBoy]8-Mar-02 7:08
memberNish [BusterBoy]8-Mar-02 7:08 
GeneralDead on.. Pin
Arno van Loenen29-Oct-01 6:54
memberArno van Loenen29-Oct-01 6:54 
QuestionHow do i add another dialog into the current app Pin
MasterMind27-Oct-01 20:46
memberMasterMind27-Oct-01 20:46 
AnswerRe: How do i add another dialog into the current app Pin
Nish [BusterBoy]27-Oct-01 21:25
memberNish [BusterBoy]27-Oct-01 21:25 
GeneralCtrl-Break on dialog app Pin
Will Rothwell17-Oct-01 22:29
memberWill Rothwell17-Oct-01 22:29 
GeneralRe: Ctrl-Break on dialog app Pin
Joseph M. Newcomer18-Oct-01 17:18
memberJoseph M. Newcomer18-Oct-01 17:18 
Generala small doubt Pin
Nish [BusterBoy]16-Oct-01 0:05
memberNish [BusterBoy]16-Oct-01 0:05 
GeneralRe: a small doubt Pin
Christian Graus16-Oct-01 16:28
memberChristian Graus16-Oct-01 16:28 
GeneralRe: a small doubt [puzzling point] Pin
Christian Graus16-Oct-01 18:30
memberChristian Graus16-Oct-01 18:30 
GeneralRe: a small doubt Pin
Joseph M. Newcomer16-Oct-01 18:27
memberJoseph M. Newcomer16-Oct-01 18:27 
GeneralRe: a small doubt Pin
Christian Graus16-Oct-01 18:36
memberChristian Graus16-Oct-01 18:36 
GeneralRe: a small doubt Pin
Christian Graus16-Oct-01 19:48
memberChristian Graus16-Oct-01 19:48 

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.171207.1 | Last Updated 16 Oct 2001
Article Copyright 2001 by Joseph M. Newcomer
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid