Last update: 2010-10-20
Windows applications often use message boxes for asking the user for some actions or for displaying information messages. From week to week, more applications are getting published, which contain nice message boxes with checkboxes like "Do not display this message again" or "Do not ask this question" again, with which the user is able to customize the application behavior and to get rid of message boxes, which he always wants to answer in the same way.
I also wanted to offer this to the users of my applications. What features should be supported?
- The message boxes should support some new style (the
MB_??? flags used in a call of
- Such message boxes should be entirely written in MFC to enable other MFC developers to make quick and easy customization without having to know much about Windows API calls, just by using the standard MFC classes.
- The new message boxes should support the checkboxes mentioned above and should manage automatically to save the state of the checkbox and the answer of the user and not to display the message box again, if the user didn't want it to appear again.
- The message boxes should also be easy to integrate into existing applications. In existing applications, I didn't want to change every line of code containing a call to
AfxMessageBox to something else. I'd just like to add a few lines of code and all messages boxes should appear in the new way.
At CodeProject, there are currently two different interesting solutions for modifying and enhancing the standard Windows message boxes, which can be invoked from MFC based applications by using the
Although these solutions work fine, there were a few problems, because of which I was forced to offer a third solution:
- Both solutions can be used in MFC based applications, but offer only little or even no support for the standard MFC classes. For example, in one application, all dialogs are not derived from the MFC
CDialog class directly, but from another class, which draws a custom skin for the dialog instead of the standard skin. If I want to use the message boxes provided by the two solutions mentioned above in this case, I have to apply many changes in the source code. My solution is entirely based upon MFC classes. It can therefore be easily modified and is for people like me, who enjoy using MFC and do not want to get deep into Windows API calls and is more easy to understand.
XMessageBox class supports "Do not ask again" or "Do not display again" checkboxes in the displayed message boxes. This feature is also supported by my
CMessageBoxDialog class. The problem with the
XMessageBox class from my point of view has been, that the state of the checkboxes, which has been stored in the registry, was stored there in a way, which is not the standard way by using the
GetProfileInt methods of the
CWinApp class. This might seem to be only a little problem, but I'd like to get the values stored in the same places as all other profile values are stored automatically by the MFC framework.
- At last, the layout of the message boxes generated by the two classes mentioned above didn't seem to me quite the way I'd like it to be, therefore I changed it a little bit.
How to Use CMessageBoxDialog
The Simple Way
The simple way to use the new message box is to change nothing in your application. All your calls to
AfxMessageBox(...) remain just the way they are already. You just have to overwrite the method
DoMessageBox in your application class, which is derived from
CWinApp. Use the following code to overwrite the method:
int CYourApplication::DoMessageBox ( LPCTSTR lpszPrompt, UINT nType,
UINT nIDPrompt )
CWnd* pParentWnd = CWnd::GetActiveWindow();
if ( pParentWnd == NULL )
pParentWnd = GetMainWnd()->GetLastActivePopup();
CMessageBoxDialog dlgMessage(pParentWnd, lpszPrompt, _T(""), nType,
Now every time you use
AfxMessageBox anywhere in your application, the new message box will appear. The new feature can simply be used by adding the new message box styles (the
MB_??? flags) to your already existing message box flags. Your example, if you do a call like this:
int nResult = AfxMessageBox(IDS_ARE_YOU_SURE_TO_QUIT,
MB_YESNO | MB_ICONQUESTION);
To add the checkbox "Don't ask again" to the message box, simply change the call to:
int nResult = AfxMessageBox(IDS_ARE_YOU_SURE_TO_QUIT,
MB_YESNO | MB_ICONQUESTION | MB_DONT_ASK_AGAIN);
The Other Way
The other way of using the new message box is to directly create a dialog object. For details, please take a look at the header file of
CMessageBoxDialog. The constructor will take the same parameters as the
AfxMessageBox method. If you create the message box this way, you can also change the displayed icon to some other icon by using the
It's also required to create the message box this way, if you want to use the timeout feature, which can be activated by calling the
SetTimeout method. A timeout is a countdown, which starts, when the message box is displayed. There are two modes for a timeout: The "un-disabled" or "enabled" timeout means, that the user can choose any button, but if he doesn't choose one, the default button will be assumed as being chosen, when the countdown is finished. The other mode, a "disabled" countdown is something like a nag screen. All buttons will be disabled, until the countdown is finished. After that, the user can click any button.
The New Styles and Return Values
Besides the standard
MB_??? flags provided by Windows, the
CMessageBoxDialog supports the following new flags:
MB_CONTINUEABORT: Display two buttons in the message box: "Continue" and "Abort".
MB_SKIPSKIPALLCANCEL: Display three buttons in the message box: "Skip", "Skip all" and "Cancel".
MB_IGNOREIGNOREALLCANCEL: Display three buttons in the message box "Ignore", "Ignore all" and "Cancel".
MB_DONT_DISPLAY_AGAIN: If you set this flag, a checkbox "Don't display this message again" will be displayed in the message box. If the user checks this checkbox, the result of the message box will automatically be stored in the registry. The next time, this dialog will be called through
AfxMessageBox or the
DoModal method of the
CMessageBoxDialog directly, the former result will be returned. You as a developer do not have to care, whether the message box is actually displayed or not. You will receive the result, the user wants you to receive - no matter whether it's a direct input or it's the input stored in the registry, because the user didn't want to be asked again.
MB_DONT_ASK_AGAIN: This flag does the same as
MB_DONT_DISPLAY_AGAIN, only the text of the checkbox will be another one: "Don't ask this question again" instead of "Don't display this message again".
MB_DEFAULT_CHECKED: If a checkbox is displayed, this box is not checked by default. If you add this flag, the checkbox will be marked checked as soon as the message box is displayed.
MB_YES_TO_ALL: If this flag is set and your message box contains a "Yes" button, an additional button with the text "Yes to all" will be added to the message box.
MB_NO_TO_ALL: This flag does the same as
MB_YES_TO_ALL, but it will add the button "No to all", if your message box contains a button named "No".
MB_RIGHT_ALIGN: If you specify this flag, the button in the dialog will be aligned on the right side of the message box (e.g. as it is done in the Windows Explorer) and will not get centered in the dialog.
MB_NO_SOUND: If you specify this flag, no standard sound will be played, if you open a message box.
MB_DEFBUTTON6: Because now there can be more than four buttons in a message box, these flags have been added to enable you to select another default button.
Because of the new buttons, there are also some new return values:
IDIGNOREALL. They represent the new buttons and will be returned, if one of these buttons is clicked.
There are also some other
public methods for the
CMessageBoxDialog class, which are explained in the header file or the source code and should be easy to understand and use.
Just one method might be interesting:
ResetMessageBoxes. If you call this method, all message box results, which have been stored in the registry, because the user checked the "Don't display again" or "Don't ask again" checkbox, are removed. Therefore all message boxes will be displayed again.
How to Use It with VC6/MFC6
To use the
CMessageBoxDialog with VC6/MFC6, some minor changes need to be applied. Please take a look at this message for more information. Because I do not have VC6/MFC6 installed, I cannot provide a full download for this case, but I think it's very easy to customize and should be no problem.
2010-10-20: Version 1.2 lite
- Added the feature that one can add buttons without needing a
static string resource
- Added the feature that the dialog is now dynamic (instead of having add a custom dialog resource)
- Removed the feature of using a checkbox to remember choice (required access to settings/registry)
- Removed the feature of using a timer to automatically choose (too complicated code)
- Removed the feature of imitating the
Messsagebox styles require access to
user32 resource to retrieve "Ok", "Cancel", etc.)
2004-03-01: Version 1.1a (Minor update)
- License: Source code now may be used under the terms of the LGPL license, too
- License: Added the full licenses to the ZIP archives
2004-02-29: Version 1.1 (Minor update)
- Bug Fix: Added missing files to the ZIP archive
- Bug Fix: Added support for the standard Windows flags
MB_RTLREADING, which were still missing
- New Feature: Added the
ResetMessageBoxes method to reset the message boxes
- New Feature: Added the
- New Feature: Added the enabled and disabled timeout for the message boxes
2004-02-28: Version 1.0 (Initial release)