Tuesday, May 20, 2008
This project provides a custom and enhanced message box replacement for the default
MsgBoxfound in Access. A Test database for Access 2007 is available at the bottom of this post. (Updated Monday 01APR2013.)
What’s wrong with the default MsgBox
The default message box in Access is sometimes useful to warn, inform or ask confirmation from the user.
It has, however, a few drawbacks:
- It is bland: the standard message box does not even follow the currently selected Office 2007 scheme.
- The amount of text it can display is limited: if you try to display too much text it will be truncated.
- You can’t copy or save the content of the message.
- Because popup boxes are viewed as intrusive, people tend not to read them and end-up closing message boxes before they realize they may have contained useful information.
- They only displays plain text: you cannot format the message to draw attention to the key points.
- They are blocking, meaning that nothing can happen in the main application while the box is displayed (it can’t even shut down).
- It will only appear on the monitor that has the main Access application window, even though the message box may have been opened from a form on another monitor.
Sometimes you need to display an important message or require users to make take a decision.
Message boxes are not to be abused but they serve a useful purpose.
An enhanced message box
Rather than using the bland standard message box you can now have something a bit more customized.
Plain Text version of the enhanced custom message box under the Office Blue Colour Scheme:
RichText version of the enhanced custom message box under the Office Black Colour Scheme:
Here are the features of the enhanced message box:
- It is entirely compatible with the standard one: just change
Boxusing find and replace should be enough (see tip below to avoid getting strange errors).
- It allows the user to simply click on a button to copy the content of the message to the clipboard or save it to a text file to a configurable default location.
- It looks and feels like it belongs to the main application, following its colour scheme.
- It attempts to prevent users from blindly closing the modal box reading the message: buttons will first be inactive for a configurable amount of time. It’s not a perfect solution, but it is quite effective.
- There is a
RichBoxversion that can display rich HTML content, not just plain text, so important parts of the message can be formatted in a useful way.
- It is able to display large amount of data. While it’s not something you usually want, it may be useful for the message box to display more text in some situations (log or tracing information, legal documentation, etc).
- Rather than sprinkling your code with “
& vbCrLf & _” uglies, you can embed newlines in the text itself by using C-style “
\n” escape sequences that will automatically be transformed into the appropriate newlines. Makes for clearer code and less typing.
- Because you get the source, you can easily customise the message box with new icons and colours to better match your overall application’s personality.
- It is non-blocking: if your application forces users to log-off after a certain amount of inactivity, the enhanced message box will just close rather than prevent Access from shutting down like the standard
MsgBoxdoes. Of course, it’s up to you to decide how to handle that gracefully, if at all.
- It properly displays the expected button captions based on the language of the operating system, so it behaves very much like the default
MsgBox(for instance, it will properly display “Cancel” on English systems and “Annuler” on French ones).
- It also properly plays the system sounds associated with the type of message. You can also enable or disable the sound effect as needed.
- As of version 1.4, it will properly display on the correct monitor in a multi-monitor setup.
How to use it
Download the demo below and copy (drag & drop) the following into your application:
If you rename the
FormDialog, make sure you replace any occurrence to it in the code, in particular in the
Since the enhanced message box is just a replacement for the standard one, you just use it like you would use the
As of version 1.4, you can also customise the button labels instead of using the default ones (thanks to Kristjan for the suggestion):
There are a few additional settings that can be used to change the behaviour of the enhanced message boxes.
One is that you can adjust the delay before the buttons become activated.
Another one is that you can enable or disable whether beeps should be played or not.
The last settings is the folder where we should save the content of the message when the user clicks the Save button on the message box.
These few settings make the enhanced message box more customizable.
MsgBox cannot display much text. On the other hand, there is no real limitation to the amount of text the
RichBox can display.
When the amount of information is too much to fit the maximum allowed size for the message box the text will overflow and can be scrolled up/down as necessary.
Limitations of the RichBox
RichBox version relies on the normal TextBox control’s ability under Access 2007 to display RichText wich is nothing more than lightweight HTML.
Because font size may be varying a lot in the message, it becomes very difficult to accurately predict the size of the box needed to display the whole message.
Short of implementing a complete HTML engine, we have to rely on some assumptions to display HTML.
The risk is that sometimes the content may not properly fit the TextBox control in some circumstances.
If you use the
RichBox, thoroughly try displaying your messages and tweak the HTML as necessary to include additional lines or non-breaking spaces to ensure that the result looks good.
If you don’t overuse font size and don’t display in multiple fonts the
RichBox should do the right thing most of the time.
Don’t overuse the
RichBox to display colourful messages. There is a fine line between being informative and tasteless. Keep colours and formatting where it is useful.
I think that in most cases, the plain text version
Box is more than enough.
Replacing MsgBox in existing code
As I said above, replacing the standard
MsgBox is easy but you need to make sure your search and replace parameters are configured correctly:
If you’re getting strange compile errors, it may be because you forgot to tick the Find Whole Word Only and some of the strings containing the letter sequence “msgbox” were replaced in the process.
If that’s the case, you can revert the damage by simply doing a search and replace across the whole project on:
VbDialog.BoxStyle to be replaced with
VbDialog.BoxResultto be replaced with
How it works
The code makes extensive use of Win32 API calls.
Most of the hard work is done in the
FomDialog class form. There is too much there to really go into the details but you are welcome to have a look at the commented code.
The code relies also on a utility function from Stephen Lebans used to calculate the size of of text. I have made some minor modification to that code so I would refer you to his original implementation if you are interested in calculating TextBox sizes for forms or reports.
In the code for the
FormDialog, I re-implement some of the expected functionalities of the
MsgBox: proper arrangement of the buttons, displaying of the appropriate icon, etc.
Once this is done, we calculate the size of the textbox needed to display the whole of the message.
In the case of RichText, we first use
Application.PlainText() to convert the HTML into properly formatted plain text. We then calculate the Textbox size using a slightly larger font than needed as a way to ensure that the content of the RichText message will fit the box in most cases.
Once we know the size of the TextBox, we can easily resize the form to properly display the TextBox.
If there is too much text, we resize the form to its maximum permissible (70% or screen width and 90% of screen height) and change some of the visual cues to let the user know the text is overflowing.
One thing of note is the way the form is kept modal.
Rather than using
DoCmd.Close I use the form as a class and create an instance manually (see the code in
Dialog.Richbox). I keep this instance alive until I got the form’s result back.
If you are interested in knowing how the form is made modal, this is the code in
FormDialog.ShowModal() what keeps the form open until the user clicks a button:
Sleep() function is a Win32 API that stops the current process for the given number of milliseconds. This in effects hands back the control to the Operating System for a short time. That way the system is still responsive and does not consume resources when it’s just waiting for user input.
You can download a sample database containing all the necessary code as well as a number of tests.
This version only contains the database in the new Microsoft Access accdb format.
Download the EnhancedMsgBox1.4.zip (142KB), v1.4 containing the ACCDB database.
It’s been a while, but at last some improvements and bug fixes!
- As per Julie B’s comment, updated code to properly display the dialog on the proper monitor in multi-monitor environments.
The dialog box will open in front of the Access window that currently has focus (assumed to be the one that opened the dialog), so if your application has forms on different monitors, the dialog should open on the right one. If we can’t determine the active window, the dialog box will open in the middle of the monitor containing the main Access application window.
- Implemented Kristjan’s suggestion regarding the use of custom button labels. See updated description above.
- Corrected background colours for the dialog box so they correctly match the MS Office theme.
- Corrected a bug in the code that decided of the correct sound to play.
Thanks to Henry of Access-Pro.de for proposing a correction to the default buttons behaviour.
- Updated behaviour for the default buttons. They are now focused in a way that matches that of the standard msgbox.
- Reversed the naming of the buttons on the form to make it a bit more consistent with the standard box.
- Corrected bug in
Form_FormDialog.FilenameSanitize()function that would fail to remove all invalid characters for a file name.
- File name for the saved text message will be truncated to first 32 characters
of message box title in
- Changed the use of
ShellExecuteto avoid security warning in some instances in
- Corrected twips to pixel conversion bug in
API_GetTextMetrics.fTextWidthOrHeight()that would result in an improperly sized dialog box when the text message was too wide.
- Corrected code for
DefaultButtonDelay(thanks to Geoffrey) (was referencing wrong variable, causing self-referencing code).
- Corrected code for
RichBoxto take the
DefaultSavedTextFileFolderinto account (the path was previously not passed onto the dialog boxes and the text file would always be created in the application folder instead of the one specified by
- Added license notice at top of source code.
- Original version
- Dissecting the MessageBox article on CodeProject
- XMessageBox -- A reverse-engineered MessageBox() article on CodeProject
- TextWidth-Height code demo from Stephen Lebans (great resource, check it out!).
- Pixel to Twips conversion from MSDN.
- Copy Text to Clipboard from the excellent site The Access Web.
- Getting Resource Strings and more from DLLs.
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
Free for re-use in any application or tutorial providing clear credit is made about the origin of the code and a link to this site is prominently displayed where end-users can easily access it.