MS Access: Enhanced Message Box Replacement

Tuesday, May 20, 2008

Microsoft Access This project provides a custom and enhanced message box replacement for the default MsgBoxfound in Access. A Test database containing all the code for Access 2007/2010/2013 is available at the bottom of this post.
(UPDATED Saturday 21OCT2014 to VERSION 1.10.)

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.

Standard MsgBox

It has, however, a few drawbacks:

  • It is bland: the standard message box does not even follow the currently selected Office colour 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:

Plaintex Enhanced Message Box

RichText version of the enhanced custom message box under the Office Black Colour Scheme:

RichText Enhanced Message Box

Here are the features of the enhanced message box:

  • It is entirely compatible with the standard one: just change MsgBox to Box using 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 RichBox version 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 MsgBox does. 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.
  • From of version 1.4, it will display on the correct monitor in a multi-monitor environment.
  • Version 1.7 adds support for Unicode escape sequences within strings to display Unicode characters in the dialog box. This was added following the publication of this article about .Net Strings in VBA.
  • Version 1.10 adds a feature that allows users to dismiss a particular message so it doesn’t appear again.

How to use it

Download the demo database below and copy (drag & drop) the following into your application:

  • the FormDialog form,
  • the Dialog module.

If you rename the FormDialog, make sure you replace any occurrence to it in the code, in particular in the Dialog module.

Since the enhanced message box is just a replacement for the standard one, you just use it like you would use the MsgBox.

    ' Simple use of the Plaintext box
    ' Note the use of n that will be converted into a newline
    Dialog.Box "This is a plaintext message.\nClick OK to dismiss",
               vbOKOnly + vbinformation, _
               "Message Title"
    ' Getting the result back
    Dim dr As vbMsgBoxresult
    dr = Dialog.Box("Are you sure you want to delete?", _
                    vbYesNoCancel + vbQuestion, "Confirm action")
    If (dr = vbYes) Then DeleteRecords
    ' Using named parameters
    Dialog.Box Prompt:="All your bases are belong to us", _
               Buttons:=(vbOkOnly + vbCritical), _
               Title:="Bad error"
    ' Using the RichBox to display simple HTML
    ' The first line will be bold, then the word 'button' will be printed in red
    ' Here the \n will be escaped to '<br/>' tags to simulate newlines.
    Dialog.RichBox "<strong>This is a bold message</strong>.\n" & _
                   "Click the <font color=""#FF0000"">button</font> to dismiss.",
                   vbOKOnly + vbInformation, _
                   "RichText Message Title"


There are a few additional settings that can be used to change the behaviour of the enhanced message boxes.

Custom buttons

You can customise the button labels instead of using the default ones (thanks to Kristjan for the suggestion):

Screenshot of dialog box with custom button labels

    ' Use custom labels. Buttons that are not labelled will not be displayed
    ' The returned value is either vbBt1, vbBt2 or vbBt3
    Dim dr As vbMsgBoxresultEx
    dr = Dialog.Box (Prompt:="This is a custom button label test.",
                     Buttons:=vbCustom + vbInformation, _
                     Title:="A custom message", _
                     LabelButton1:="Hit Button 1!", _
                     LabelButton2:="No!, Me! Me!", _
                     LabelButton3:="Forget it!")
    If (dr = vbBt1) Then Debug.Print "Button 1 pressed!"
    ElseIf (dr = vbBt2) Then Debug.Print "Button 2 pressed!"
    ElseIf (dr = vbBt3) Then Debug.Print "Button 3 pressed!"

Button delay

One is that you can adjust the delay before the buttons become activated.

    ' Use the ButtonDelay to specify the time in seconds before the buttons become activated
    ' The default is 2s. Use 0 to activate the buttons immediately.
    Dialog.Box Prompt:="All your bases are belong to us", _
               Buttons:=(vbOkOnly + vbCritical), _
               Title:="Bad error", _
    ' Change the default delay value.
    ' To disable the activation delay
    Dialog.DefaultButtonDelay = 0
    ' To make the user wait 3 seconds before they can press any button
    Dialog.DefaultButtonDelay = 3


Another one is that you can enable or disable whether beeps should be played or not.

    ' Use AllowBeep to specify whether beeps should be played when the message box opens
    ' By default, they are.
    Dialog.Box Prompt:="All your bases are belong to us", _
               Buttons:=(vbOkOnly + vbCritical), _
               Title:="Bad error", _
    ' Change the default behaviour. This is True by default.
    Dialog.DefaultAllowBeep = False

Hide Buttons

You can also hide the Copy to clipboard and save to File buttons which are normally visible by default.

    ' Use AllowCopyToClipboard and AllowSaveToFile to specify whether to display
    ' the copy to clipboard and save to file buttons.
    ' By default, they are visible, but here we hide them.
    Dialog.Box Prompt:="All your bases are belong to us", _
               Buttons:=(vbOkOnly + vbCritical), _
               Title:="Bad error", _
               AllowCopyToClipboard:=False, _
    ' Change the default behaviour. This is True by default.
    Dialog.DefaultCopyToClipboardAllowed = False
    Dialog.DefaultSaveToFileAllowed = False

Save Folder

It is recommended to set the the folder where we should save the content of the message when the user clicks the Save button on the message box.

    ' Change the save folder.
    ' By default, the text messages will be saved in the same directory as the database.
    ' Here we want them to be saved to a temp directory
    Dialog.DefaultSavedTextFileFolder = "C\:temp"

These few settings make the enhanced message box more customizable.

Raw text and paths

By default, the enhanced dialog box will escape certain sequences in the message to convert them to their printable version:

  • Escape sequences like \n and \t are converted to newlines and tabs spaces
  • Unicode sequences are converted to their symbol: \u20ac is converted to the euro symbol .

If you do not want this behaviour (for instance you need to display data that contains lots of \ characters), use the NoStrEsc option:

    ' By default, all messages are unescaped.
    ' Here however, we want to disable that so we can display
    Dialog.Box Prompt:="A path c:\my\doc\file.doc", _
    ' Change the default behaviour. This is False by default.
    Dialog.DefaultNoStrEsc = True

Alternatively, you can use the helper function dialog.EscBackslash():

    ' Use EscBackslash() when you only want some portion of text
    ' to display '\' correctly, like paths.
    ' Here however, we want to disable that so we can display
    Dialog.Box Prompt:="A path " & EscBackslash("c:\my\doc\file.doc")

Don’t display this message again

Based on suggestions (and on a feature I wanted to implement for a while), I added a way to allow the user to choose not to display a particular message again.

Note that this feature will only work for dialog boxes displaying a single vbOKOnly button. It makes some sense since if you ask the user to choose between multiple actions, you can’t really expect their choice to be the same every time the message is displayed.

To make the dialog box dismissable, you only need to provide it with a unique ID for the message, using the DismissID option:

    ' Use DismissID to allow the user to never show the message again.
    Dialog.Box Prompt:="An annoying warning message", _
               Buttons:= vbOKOnly + vbExclamation


The user can then tick the box and this particular message will never be shown again (unless we reset the setting for it).

To ensure that the user’s choice is remembered even if the Access application is updated, the message’s DismissID is stored in the registry under:
HKCU\Software\VB and VBA Program Settings\<AppFileName>\DialogBox, where <AppFileName> is simply the name of your Access file (without the path).

You can easily re-enable a particular message or all messages from your code:

    ' Re-enable the display of a previously dismissed message:
    Dialog.ResetDismissID "1234ABC"
    ' Re-enable the display of all messages:

Large text

The standard MsgBox cannot display much text. On the other hand, there is no real limitation to the amount of text the Box and 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

The 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.

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% of 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.OpenForm and DoCmd.Close I use the form as a class and create an instance manually (see the code in Dialog.Box and 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:

    Public Function ShowModal() As VbMsgBoxResult
        ' Here we reset the result for the clicked button such as vbOK, vbYes, etc
        ' This is set in each Button's Click event
        m_Result = -1
        ' Wait for the user to click a button
        Do While (m_Result = -1)
            Sleep 50
        ShowModal = m_Result
    End Function

The 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.

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:

Search and replace options

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:
VbboxStyle or VbDialog.BoxStyle to be replaced with VbMsgBoxStyle
VbboxResult or VbDialog.BoxResultto be replaced with VbMsgBoxResult

Upgrading from an older version

If you are already using the enhanced DialogBox, upgrading to the newest version is simple.

In your Access application:

  • delete the FormDialog form,
  • delete the Dialog module.
  • delete the API_GetTextMetrics module if you have it (used in versions before 1.5)

Download the new version of the demo database below and open it.

  • drag and drop the `FormDialog to your application
  • drag and drop the Dialog module to your application

That’s all you need to do.

Code and demo database

You can download a database containing all the necessary code as well as a number of tests.
This version contains the database in Microsoft Access accdb format (the code relies on features that don’t exist in pre-2007 versions of Access).


Download Download the (177KB), version 1.10 – 21OCT2014 containing the ACCDB database.

Code Updates

v1.10: 21OCT2014
Corrected minor bugs and added new features:

  • Added dialog.EscPath() to escape paths in your message and display them correctly, as suggested by Mark Singer in comment 115.
  • Added option NoStrEsc to display raw text when you don’t want escape and unicode sequences like ‘\n’ and ‘\u20ac’ to be converted at all in your whole message.
  • Modified the code for FileExists() to avoid the issue raised by Matthias Kläy in comment 116
  • Added option DismissID to allow the user to choose to prevent a message from displaying again (suggested by David Dewick in comment 110).

v1.9: 03FEB2014
Corrected some bugs and added some options:

  • Corrected bugs that would throw exceptions when a message would contain some file path whose ‘\’ would be wrongly interpreted as an escape sequence.
  • Added options to show the buttons for copying the message to the clipboard or saving it to file.

v1.8: 28SEP2013
Resolved some Unicode-related bugs:

  • Corrected bugs that would truncate the strings in the dialog box when they contain some Unicode characters.
  • Corrected bug with copy-to-clipboard that was not copying Unicode text.
  • Corrected bug with copy-to-file that was not saving Unicode text properly.

v1.7: 13SEP2013
Added support for character literals in strings and Unicode escape sequences as supported in .Net strings.
See using .Net strings in VBA for fun an profit for details.

v1.6: 29JUN2013
Corrected issues pointed out by Joseph Strickland (thanks) when running under Office 2010 x64.
Code updated and tested under a Virtual Machine running Win8 x64 and Office 2010 x64.

v1.5: 23JUN2013
Many thanks to contributors Steve Spiller, Jiriki and Kytu for improving and pointing out issues. See details below.

  • Moved the code from the API_GetTextMetrics module into the FormDialog class to reduce the number of necessary files (now only FormDialog and Dialog objects are necessary).
  • Corrected bugs on the test form (button delay and beep options on the form were not wired up correctly in the test form)
  • RichBox was not initialising its buttonDelay correctly, resulting in the first call to use a 0 delay instead of the DefaultButtonDelay value.
  • Corrected bug reported by Jiriki on 06JUN2013 (when the ButtonDelay was set to 0, the dialog would just close the first time the dialog was opened).
  • Focus issues should be solved: the buttons are now properly focused and will behave as the standard dialog box (you can hit ENTER or ESC on the keyboard once the buttons are visible to confirm the default dialog action or cancel it).
  • Addressed parent form focus issue mentioned by KyTu on 19JUN2013: when closing the dialog, the parent form will be properly focused instead of the Navigation Panel.
  • Now supports both x86 and x64 Office systems (32 and 64 bits versions of MSAccess). Many thanks to Steve Spiller for sending me the updated database.

v1.4: 01APR2013
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.

v1.3: 17MAR2009
Thanks to Henry of 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.

v1.2: 07SEP2008
Thanks to Andy Colonna ( for uncovering the following bugs (check out his free Spell Checker with source code!):

  • 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 Form_FormDialog.MakeFriendlyFileName().
  • Changed the use of FollowHyperlink to ShellExecute to avoid security warning in some instances in Form_FormDialog.btCopyToFile_Click()
  • 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.

v1.1: 08AUG2008

  • Corrected code for DefaultButtonDelay (thanks to Geoffrey) (was referencing wrong variable, causing self-referencing code).
  • Corrected code for Box and RichBox to take the DefaultSavedTextFileFolder into 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 DefaultSavedTextFileFolder)
  • Added license notice at top of source code.

v1.0: 20MAY2008

  • Original version


Creative Commons License
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.

Entry Filed under  :  .Net,Business,Database,MSAccess,Programming

150 Comments Add your own

  • 1. David  |  February 13th, 2010 at 9:53 pm

    Sir, this is most excellent! Thanks for sharing.

  • 2. John  |  February 16th, 2010 at 4:29 pm

    I have downloaded your example database. I’m using Access 2007 but something odd happens. Non of the buttons on the test form seems to activate a trigger. In short, nothing happens. Do you have an explaination for that?

  • 3. Bob Robinson  |  April 16th, 2010 at 8:57 pm

    I would like to use vba code to close a message boc programmatically, as Matthew Pfluger suggest he can do in his July 23rd, 2009 message. Can someone please tell me how to do this.

    I too am an avid user of your message box replacement.

    Thanks. Bob Robinson

  • 4. Dave  |  May 25th, 2010 at 10:08 pm

    This looks very useful, could you please post the source code so those of us not using 2007 can have a go at extracting those parts that will work in earlier versions?

    Many Thanks,


  • 5. Deleted Image displayed w&hellip  |  June 17th, 2010 at 7:02 pm

    […] found the custom message boxes at…x-replacement/ and edited it to fit my needs — Background colours, borders, etc as well as the Images […]

  • 6. Ken Warthen  |  October 27th, 2010 at 2:15 am

    Do you know of any similar utility for MS Excel?


  • 7. MsgBox Placement&hellip  |  December 27th, 2010 at 3:45 am

    […] really but you can create your own:…-replacement/## __________________ (RG for short) aka Allan Bunch MS Access MVP – WinXP Pro, Win7 Pro- acXP, […]

  • 8. Sooz  |  January 25th, 2011 at 2:42 am

    A nice replacement message box, that solves the problem (found under Access 2010) of dialog boxes stopping being ‘modal’ before the user presses a button!

    However, the png graphics image files would really be appreciated…

    My app has to be capable of running under Access 2003, 2007 and 2010 so to keep a similar look and feel I need to create some bitmaps for the old version.

  • 9. Greg  |  February 5th, 2011 at 4:17 am

    Superb! Just came across this, it has given my application a “finished” look. One question, how do I force the application to close after the Dialog.RichBox appears, I checked the example and the check box does not fire any code.

    Cheers Greg

  • 10. Mario  |  September 20th, 2011 at 9:34 am

    This message boxes are very nice, they really make your app to look better, I was using them for awhil but then decided to change to Office 2010 64 bits and they dont work anymore, .

  • 11. Dan  |  December 9th, 2011 at 6:10 am

    I’m asking before I even try, so forgive me if this is basic. I really like the idea of this message box, however a lot of my databases use macros to run a series of queries, then display a message box when done. How can I call this message box from within a macro?

  • 12. JS  |  January 2nd, 2012 at 7:18 pm

    I love the idea of this message box, but I do not use Access, I use Excel, Word and PPT. Would it obe possible to post the text VBA code for the Enhanced Message Box Replacement (instead of an accdb file)? Tks, JS

  • 13. Tim  |  February 1st, 2012 at 1:56 am

    It’s working now! Thanks!

  • 14. UdeA  |  May 8th, 2012 at 11:29 am

    Hi Friend,

    Your enhanced MsgBox function is Great. No Errors found. Keep Up the Good work.

    UDeA From Colombo – Sri Lanka.

  • 15. Paul Trotman  |  May 18th, 2012 at 3:46 pm

    Interesting work-around. Where should the code to change the default button delay be placed. “Dialog.defaultbuttondelay = 5”

  • 16. Renaud Bompuis  |  May 18th, 2012 at 5:54 pm

    @Paut Trotman: you can place the code for setting the default options wherever you want. It only needs to be set once. Ideally, it should be part of your startup code when you launch your application, either using an AutoExec macro, or a startup Form.

  • 17. Lxocram  |  May 21st, 2012 at 4:31 pm

    You have it as an optional parameter on the Dialog.Box function

    Public Function Box(ByVal Prompt As String, _
                           Optional ByVal Buttons As VbMsgBoxStyle = vbOKOnly, _
                           Optional ByVal Title As String = "", _
                           Optional ByVal HelpFile As String = "", _
                           Optional ByVal HelpContextId As Long = 0, _
                           Optional ByVal ButtonDelay As Long = -1, _
                           Optional ByVal AllowBeep As Variant) _
                           As VbMsgBoxResult

    And there is a Private Const DEFAULT_BUTTON_DELAY = 1

    You can also override it in the form_open event of Form_FormDialog m_ButtonDelay = 2 (whole app has same delay)

    but I suggest you set the DEFAULT_BUTTON_DELAY in class Dialog.
    That way you can call Dialog.Box and either use the default or set it via optional parameter

  • 18. kmack11  |  September 12th, 2012 at 10:38 am

    Great Mod…. Have receive a Compile Error the code in vb that states that User Defined Type not defined. Is there any particular reference that i need to be sure that is set for this code to compile?

    Private m_Buttons As VbDialog.BoxStyle
    Private m_Title As String
    Private m_Prompt As String
    Private m_ButtonDelay As Long
    Private m_IsRichText As Boolean
    Private m_Result As VbDialog.BoxResult
    Private m_PlaintextPrompt  As String
    Private m_SavedTextFileFolder As String
    Private m_AllowBeep As Boolean
  • 19. oneD  |  January 4th, 2013 at 8:07 am

    I cant add this to my DB. I copied both modules and try the code, but dont working. Then i open new blank form on sample DB, ant its working. I’m using Access 2010. Any idea what to do?

  • 20. Kristjan  |  February 10th, 2013 at 5:56 am

    A really good work.
    But I wanted to give the buttons an own name.
    I couldn’t find a possiblity to write – bt1.caption="Text" – before the
    So I declared 3 public variables: Public Button1_Sgl As String, Public Button2_Sgl As String, Public Button3_Sgl As String

    Into the Sub SetUpButtons() I insert:

    If Button1_Sgl = "" Then
        Button1_Sgl = "bt1"
    End If
    If Button2_Sgl = "" Then
        Button2_Sgl = "bt2"
    End If
    If Button3_Sgl = "" Then
        Button3_Sgl = "bt3"
    End If
    bt1.caption = Button1_Sgl
    bt2.caption = Button2_Sgl
    bt3.caption = Button3_Sgl
    ' Detect which buttons to display
    If (m_Buttons And vbRetryCancel) = vbRetryCancel Then
        bt3.Visible = False
        bt2.Visible = True
        bt2.Tag = vbRetry
        If bt2.caption = "bt2" Then
           bt2.caption = GetUser32ResourceString(RES_BT_Retry)
        End If
        bt1.Visible = True
        bt1.Tag = vbCancel
        If bt1.caption = "bt1" Then
           bt1.caption = GetUser32ResourceString(RES_BT_Cancel)
        End If
        bt1.Cancel = True
    ElseIf (m_Buttons And vbYesNo) = vbYesNo Then
        bt3.Visible = False
        bt2.Visible = True
        bt2.Tag = vbYes
        If bt2.caption = "bt2" Then
           bt2.caption = GetUser32ResourceString(RES_BT_Yes)
        End If
        bt1.Visible = True
        bt1.Tag = vbNo
        If bt1.caption = "bt1" Then
           bt1.caption = GetUser32ResourceString(RES_BT_No)
        End If
        bt1.Cancel = True
    ElseIf (m_Buttons And vbYesNoCancel) = vbYesNoCancel Then
        bt3.Visible = True
        bt3.Tag = vbYes
        If bt3.caption = "bt3" Then
           bt3.caption = GetUser32ResourceString(RES_BT_Yes)
        End If
        bt2.Visible = True
        bt2.Tag = vbNo
        If bt2.caption = "bt2" Then
           bt2.caption = GetUser32ResourceString(RES_BT_No)
        End If
        bt1.Visible = True
        bt1.Tag = vbCancel
        If bt1.caption = "bt1" Then
           bt1.caption = GetUser32ResourceString(RES_BT_Cancel)
        End If
        bt1.Cancel = True
    ElseIf (m_Buttons And vbAbortRetryIgnore) = vbAbortRetryIgnore Then
        bt3.Visible = True
        bt3.Tag = vbAbort
        If bt3.caption = "bt3" Then
           bt3.caption = GetUser32ResourceString(RES_BT_Abort)
        End If
        bt2.Visible = True
        bt2.Tag = vbRetry
        If bt2.caption = "bt2" Then
           bt2.caption = GetUser32ResourceString(RES_BT_Retry)
        End If
        bt1.Visible = True
        bt1.Tag = vbIgnore
        If bt1.caption = "bt1" Then
           bt1.caption = GetUser32ResourceString(RES_BT_Ignore)
        End If
        bt1.Cancel = True
    ElseIf (m_Buttons And vbOKCancel) = vbOKCancel Then
        bt3.Visible = False
        bt2.Visible = True
        bt2.Tag = vbOK
        If bt2.caption = "bt2" Then
           bt2.caption = GetUser32ResourceString(RES_BT_OK)
        End If
        bt1.Visible = True
        bt1.Tag = vbCancel
        If bt1.caption = "bt1" Then
           bt1.caption = GetUser32ResourceString(RES_BT_Cancel)
        End If
        bt1.Cancel = True
        bt3.Visible = False
        bt2.Visible = False
        bt1.Visible = True
        bt1.Tag = vbOK
        If bt1.caption = "bt1" Then
           bt1.caption = GetUser32ResourceString(RES_BT_OK)
        End If
        bt1.Cancel = True
    End If
    Button1_Sgl = ""
    Button2_Sgl = ""
    Button3_Sgl = ""
    End Sub

    Now I write the Messagebox:

    Button1_Sgl = "Mieterdaten"
    Button2_Sgl = "Adresse"
    Mldg_S = "Sollen die Daten des Mietvertrages verwendet werden?\n\noder soll eingetragen werden:\nnur die Adresse?\nnur die Mieterdaten?"
    Select Case Dialog.Box(Mldg_S, vbQuestion + vbYesNoCancel, "Datentransfer")
      Case vbYes
            If s = "Wohnraum#" Then
              FlagWohnR_b = True
              FlagWohnR_b = False
            End If
      Case vbNo
            FlagWohnR_b = True
            FlagAdresse_B = True
      Case vbCancel
            FlagWohnR_b = True
            FlagMieter_B = True
    End Select

    Now it is perfect. But you know may be a better solution.
    Thanks for this excellent code, Kristjan – Berlin

  • 21. Gustav Brock  |  February 15th, 2013 at 1:14 am

    Thanks! Very neat. I was looking for a MsgBox with an Information icon but no beep.

  • 22. Concentus  |  February 22nd, 2013 at 5:15 am

    Works great! Thanks for sharing this. I’ve been using Peterssoftware’s ForceShutdown to allow me to do updates on my database when users left it open. But MsgBoxes were causing it to hang. I replaced all MsgBoxes with Dialog.Box in the main entry forms and it works great. Plus the enhanced features add a lot. Has saved me a lot of time. Do you have a Donate button?

  • 23. Julie B  |  March 29th, 2013 at 4:41 pm

    Just tried it on my app – looks great and love the feel, however, my clients and I run dual monitors and it appears that the message box defaults to the primary monitor. How can I get message to appear over the screen displaying the app ??? Thanks

  • 24. Renaud Bompuis  |  April 1st, 2013 at 3:47 pm

    A new version is out (v1.4), please comment below if you have any problem or suggestions.
    The article has been updated to reflect and explain the changes.
    Read the Code Update section for details.


  • 25. Julie B  |  April 8th, 2013 at 8:59 am

    Thank you so much for your quick response and time to make life so much easier for people like us who bang our heads consistently wondering “how to….”. Taking away this second level of confusion (i.e. monitors) has now given my app a degree of professionalism and one which I will be confident to install on any dunderheads desktop. Thank you again

  • 26. Frederick  |  April 19th, 2013 at 2:52 pm


    First of all, thanks for sharing this. Everything works fine, except when I try to use it as followed.
    I have a report that is a sort of letter. The text in this report varies based on the info that is found in the query where it is based on (if a certain document is not present it is set on false and the report will display the text where it asks for that document).

    This report is output to a pdf-file. There is one piece of data that can not be found in any table and/query. Therefore I ask the user of the database if they want to include the question in the report.
    The only way I figured out to do that is to put the msgbox into a function and call that function from within the report. If I use the instead of the msgbox, Access shows a empty form with the title, but without the question and the buttons and the whole database becomes unresponsive. Any idea why?


  • 27. Frederick  |  April 19th, 2013 at 4:51 pm

    Same if I use it in a Form_Close()


  • 28. Peter Cole  |  May 6th, 2013 at 11:39 pm

    Great replacement. I have an enhanced version of your 1.4 including Access 2010 Themes. Nice shaped buttons and colour scheme to match the end users colours. I will send you a copy if you can let me know an address.

  • 29. Steve Kocmoud  |  May 27th, 2013 at 1:29 pm

    Searched (with considerable skepticism) for a solution to Access Message Boxes opening off-screen. I have a 3-display system and a database form that runs in a pop-up with the Access window minimized (acCmdAppMinimize).

    While the Access window is visible, MsgBoxes position correctly; but when the window is minimized, they move to another display (for no apparent reason).
    Even though your Enhanced Message Box Replacement made no promises about MsgBoxes initiated by Pop-Ups while the Access window is hidden, it nevertheless solved the problem completely.
    Moreover (perhaps best of all), implementation and behavior were EXACTLY as specified (a rare treat in a world where much is promised while some, at most, is delivered).

    Thank you so very much!
    Your App has already been very useful and your code will, no doubt. be exemplary.
    I’m forever looking for ways to tweak Microsoft APIs.

    Live long and prosper!

  • 30. Jiriki  |  June 6th, 2013 at 11:12 pm

    Absolutely wonderful work!

    I do have a bit of a question though. If I set the buttonDelay to 0, when I call either .Box or .Richbox, either with custom buttons or simple defined (e.g. vbOKOnly), it automatically ‘answers’ the dialog, as if the user clicked.
    It’s instantaneous, however, if I do a step through at or before the method call, the Dialog form is shown properly, waiting user input.
    If I set the delay to any positive value or leave blank (default 2sec) it always waits.

    The returned value on the ‘auto-answer’ is 1 if any of the OK/Yes type built in and 101 for custom buttons. If I call it twice in a row, the second call waits for user input as intended.

    I was able to reproduce this with the example .accdb from the site as well, so I don’t think I’m introducing anything into the code. I have Office 2010 Pro (Access v14.0.6129) 32bit running on Win7 64bit.

    Again great work and I can get by with a 1sec delay, but just wondering if this has been seen or if I’m doing something blatantly silly.

    Example code:

    Sub Test1()
        Dim nResult
        Dim sAuth
        Dim sSSO
        Dim sStatus
        Dim sLbl1, sLbl2, sLbl3
        sSSO = "MyName"
        sAuth = "MyAuth"
        sStatus = "MyStatus"
        sLbl1 = "Option1"
        sLbl2 = "Option2"
        sLbl3 = "Option3"
            nResult = Box(Prompt:="Set " & sAuth & " authorization for " & sSSO & IIf(sStatus <> "", "?" & vbCrLf & vbCrLf & "Currently set to '" & sStatus & "'", "...?"), _
                          Buttons:=vbOKCancel + vbInformation, _
                          Title:="Set " & sAuth, _
            MsgBox "Result is: " & nResult & vbCrLf & vbCrLf & "Yes = " & vbOK & " Cancel = " & vbCancel, vbInformation, "DEBUG"
            nResult = Box(Prompt:="Set " & sAuth & " authorization for " & sSSO & IIf(sStatus <> "", "?" & vbCrLf & vbCrLf & "Currently set to '" & sStatus & "'", "...?"), _
                          Buttons:=vbCustom + vbInformation, _
                          Title:="Set " & sAuth, _
                          LabelButton1:=sLbl1, _
                          LabelButton2:=sLbl2, _
                          LabelButton3:=sLbl3, _
            MsgBox "Result is: " & nResult & vbCrLf & vbCrLf & "Yes = " & vbYes & " No = " & vbNo, vbInformation, "DEBUG"
    End Sub
  • 31. Fred  |  June 14th, 2013 at 8:00 pm

    Hi there,

    Like the look of this. Not sure if I’m being thick, though!

    I have set up a prompt telling users that a certain process takes a few seconds to complete. I thought that this would pop up a message box, but allow the process to continue in the background. However, the application stops and waits for the user to click the ok button. I have stripped the code to simply:

    Dialog.Box "Please wait - processing request. This usually take about 15 seconds...", vbExclamation + vbOKOnly, , , , 5
    Debug.Print Time

    The time is not output until after the message box is closed. Is there something I’m doing wrong?

  • 32. Fred  |  June 14th, 2013 at 8:01 pm

    Sorry the above should be:

    Dialog.Box "Please wait - processing request. This usually take about 15 seconds...", vbExclamation + vbOKOnly, "Complete Item List", , , 5
    Debug.Print "Start filling table at " & Time
  • 33. Lxocram  |  June 14th, 2013 at 10:11 pm


    Access has no “background query” or threads. So while query’s are running the interface does not respond.

    *So either you show dialog first and only when user clicks ok query starts *Or you execute query first -> no point in having a dialog

    You can work around this by executing the query in the background on the backend server and at the end of the process setting some data_flag “finished” on

    1. sent command “Start background query”
    2. Show dialog (while “busy waiting” show “still loading” and check each second wether data_flag finished is on) That way the dialog/access interface remains responsive
  • 34. Fred  |  June 14th, 2013 at 10:34 pm

    @Lxocram: Thanks for that. TBH it is a temporary fix for a nasty piece of code I had to slap together in 5 mins until I get time to optimise and do properly. A little box saying something is going to happen/is happening gives the illusion of better performance :)

  • 35. Regina Beauregard  |  June 17th, 2013 at 3:34 am

    I love the enhanced message box and I use it throughout one of my applications. However, I have been unable to successfully modify your example below for the Rich Text message box. Is this possible. Can you help me out here. Don’t want two types of message boxes in this one application.

    Dim dr as vbMsgBoxresult dr = Dialog.Box("Are you sure you want to delete?", _ vbYesNoCancel+vbQuestion, "Confirm action") if (dr = vbYes) then DeleteRecords

  • 36. Fred  |  June 17th, 2013 at 5:47 pm

    I have a new system, which has Office 2010 x64 edition. This does not work with x64 as is. Before I spend time hacking away to see if I can get x64 compatibility, is there one already existing?

    If not and I do get it working, do you want a copy?

  • 37. Fred  |  June 17th, 2013 at 9:46 pm

    @rigina try: Dim dr as Integer dr = Dialog.Box(“Are you sure you want to delete?”, _ vbYesNoCancel+vbQuestion, “Confirm action”) if dr = vbYes then DeleteRecords

    Not tried it in any way, but that is how I capture and test the response with standard MsgBox. The drop-in replacement Dialog.Box seems to be working in my code…

  • 38. Regina Beauregard  |  June 17th, 2013 at 9:51 pm

    Thanks Fred, I did have the standard Diaglog Box working but I was having trouble with the Rich Text Box. I am all set now. I am using the code below and it works fine. Don’t know why I was having a problem.

    Dim dr As VbMsgBoxResult dr = Dialog.RichBox("Your selections will not be saved, Do you want to continue?", _ vbYesNo + vbQuestion, "Confirm action") If (dr = vbYes) Then DoCmd.OpenForm "frmFields" DoCmd.Close acForm, Me.Name Else 'Do Nothing EndIf

  • 39. Fred  |  June 17th, 2013 at 9:57 pm

    My mistake, meant to type Dialog.RichBox not just box…

  • 40. KyTu  |  June 19th, 2013 at 4:44 pm

    This is awesome and really what I need!

    Thank you very much for all of your efforts to create this wonderful thing for us!

    However, I found out one thing strange that after the is closed, the focus is moved to object in Access navigation panel, not the current opened form.

    This causes problem when I open form record then hit duplicate button, is opened to ask if I want to duplicate the record, I hit yes and then instead of duplicate the current record, an Access “Paste As” box opened (which is same as when you copy and paste a object in Navigation panel.

    Can you advise solution here?

    Thank you very much!

  • 41. Gary O  |  June 20th, 2013 at 8:40 am

    To clarify upgrading to the latest version, is it just a matter of deleting the 2 modules from the old version, and then importing the 2 new modules?

  • 42. Gary O  |  June 20th, 2013 at 9:05 am

    UPDATE – Oops, forgot to import the dialog form. All good now.

  • 43. Renaud Bompuis  |  June 23rd, 2013 at 10:40 am

    A new version is out today (v1.5), please comment below if you have any problem or suggestions.

    Read the Code Update section for details.


  • 44. Joseph Strickland  |  June 28th, 2013 at 10:05 pm

    Enhanced msgbox worked perfectly for a couple years after switching to window 8 no text in msgbox buttons. Buttons are blank, please help. windows 8 pro 64bit access 2010 64bit

  • 45. Renaud Bompuis  |  June 29th, 2013 at 9:56 pm

    @Joseph Strickland: I have updated the code and issued version 1.6 with the corrections.
    Please let me know if there are any issues.

  • 46. KyTu  |  July 1st, 2013 at 3:49 pm

    Hi Renaud,

    Thank you so much for your hard work!

    This is wonderful

    If I find any issue, I’ll let you know!


  • 47. steve  |  August 21st, 2013 at 8:12 pm


    just wanted to say a big thank you, this is fantastic many many thanks


  • 48. Renaud Bompuis  |  September 13th, 2013 at 6:56 pm

    A new version is out today (v1.7), please comment below if you have any problem or suggestions. Read the Code Update section for details. Thanks!

  • 49. Uros  |  October 1st, 2013 at 6:37 pm


    First I must say thanks for great work. I like this MsgBox, verymuch :).

    But I have one problem. In some situations i get empty msgbox, no picture, no text and access stay in loop. When I press Break, code stop in function ShowModal in loop ‘wait until the form becomes hidden …’.

    I get This problem only when I develop code. I think when access, becouse of some error in code (object not exist, …), chrash. Code probably use some global variable and this variable go out when access chrash…..

    Can somebody have the same problem?

    Regards, Uros

  • 50. Mark Singer  |  October 26th, 2013 at 5:39 am

    First I’d like to say that this Message Box is really nice and I look forward to making use of it. Thanks for your efforts!

    A couple of questions:

    I can’t seem to get the colors to appear when I specify a font color. For example, Dialog.RichBox "FAIL - ERROR HANDLER TRIGGERED", vbInformation + vbOKOnly, "Test", , , 1 will not display the text in red even though the same “….” code works in the browser. Any ideas?

    Is there a limit to the amount of text that can be shown? Will the message text scroll within the window if there are more than X lines? Is there a limit on the vertical size of the message box? I ask because, everything appears correctly and completely when I use the default size but if I specify , the text wraps incorrectly and is cut off at the bottom of the box so that last 3 or 4 lines don’t show.



Leave a Comment

(Will not be shown)

Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Trackback this post  |  Subscribe to the comments via RSS Feed


Renaud This is a simple technical weblog where I dump thoughts and experiences from my computer-related world.
It is mostly focused on software development but I also have wider interests and dabble in architecture, business and system administration.
More About me…

My StackOverflow Profile
My (sporadically active) StackOVerflow account

Most Recent Posts