Code Samples for Businesses, Schools & Developers

First Published 28 Oct 2026



The standard VBA message boxes are always centred on the screen, have small font size (8pt?) and cannot be zoomed (other than by using Windows scaling).

With modern monitors and typical resolutions of 1920 x 1080 or higher, the text can be difficult to read comfortably, even for users whose eyesight is reasonably good.
The centred positioning can also mean that users often need to move the message box to one side before acting on its contents.

The MsgBoxPZ (position/zoom) function overcomes both of these issues by allowing developers/users to control where a message opens and to adjust its zoom level.

This project was begun by my colleague Xevi Batlle with the assistance of Gemini/Antigravity AI.
I then further modified the functionality to allow the message box to be docked to specific positions on the screen.

There are many message box alternatives that use custom forms that imitate or enhance the Access VBA message box (MsgBox).
This project is different as it doesn’t replicate the VBA MsgBox. It modifies the appearance and scaling of the built-in message box and adds the ability to set its position.



The MsgBoxPZ function

To allow message boxes to be positioned and zoomed, the MsgBoxPZ function adds three additional arguments Left/Top/Zoom to the default VBA MsgBox function:

Syntax:     Items in [ ] are optional

MsgBoxPZ (Prompt, [Buttons], [Title], [HelpFile], [Context], [Left], [Top], [Zoom])


The last 3 optional arguments have default values as below:
•   Left: default = -1 (centred). Other values in twips specify the left position on screen
•   Top: default = -1 (centred). Other values in twips specify the top position on screen
•   Zoom: default = 100 (%) with the allowed percentage zoom range from 10 to 1000

The full MsgBoxPZ function code is:

' ==============================================================================
' PUBLIC FUNCTION: MsgBoxPZ (Position & Zoom)
' ==============================================================================
Public Function MsgBoxPZ( _
ByVal Prompt As String, _
Optional ByVal Buttons As VbMsgBoxStyle = vbOKOnly, _
Optional ByVal Title As String = vbNullString, _
Optional ByVal HelpFile As String = vbNullString, _
Optional ByVal Context As Long = 0, _
Optional ByVal Left As Long = -1, _
Optional ByVal Top As Long = -1, _
Optional ByVal Zoom As Single = 100) As VbMsgBoxResult

If Title = vbNullString Then
Title = Application.Name
End If

m_TargetdialogTitle = Title
m_PromptText = Prompt
m_IsInputBox = False
m_MsgBoxIconStyle = (Buttons And &H70)
m_hCustomIcon = 0
m_hPromptEdit = 0
m_IsHeightClamped = False
m_RequiresScroll = False
m_RequiresScroll = False

' Parse zoom percentage (Single value, clamped between MIN_ZOOM_PERCENT and MAX_ZOOM_PERCENT)
Dim safeZoomPercent As Single
safeZoomPercent = ParseZoom(Zoom)
m_ZoomFactor = CDbl(safeZoomPercent) / 100

' Coordinate setup (Twips to Pixels with display DPI awareness)
If Left >= 0 And Top >= 0 Then
' If Nz(Left, -1) <> -1 And Nz(Top, -1) <> -1 Then
Dim twipsPerPixelX As Double, twipsPerPixelY As Double
CalculateTwipsPerPixel twipsPerPixelX, twipsPerPixelY
m_TargetPixelX = CLng(Left / twipsPerPixelX)
m_TargetPixelY = CLng(Top / twipsPerPixelY)
Else
m_TargetPixelX = -1
m_TargetPixelY = -1
End If

m_TimerElapsedTicks = 0
m_PrevWndProc = 0
m_hScaledFont = 0
m_SubclassedHwnd = 0
m_SplitPixelY = 0

' Always activate timer to ensure height bounds clamping and text scrolling checks occur
m_TimerHandle = SetTimer(0, TIMER_IDENTIFIER, 10, AddressOf dialogTimerProc)

' Invoke native dialog box
If Len(HelpFile) > 0 Then
MsgBoxPZ = MsgBox(Prompt, Buttons, Title, HelpFile, Context)
Else
MsgBoxPZ = MsgBox(Prompt, Buttons, Title)
End If

' Comprehensive cleanup of resources
CleanupHookResources
End Function


The standard MsgBox function is an integral part of VBA and incorporating this additional functionality required a very large number of APIs, types and constants.

It also depends on a large number of support procedures:
•   CleanupHookResources
•   ParseZoom
•   MsgBoxTimerProc
•   dialogTimerProc
•   HasEditControl
•   GetdialogWorkArea
•   GetFontLineHeight
•   ApplyZoomAndPosition
•   InitialiseScaledFont
•   GetStockIconIdentifier
•   ExtractModernStockIcon
•   IsButtonControl
•   IsEditControl
•   IsPromptTextControl
•   CalculateTextHeight
•   ScaleMsgBoxControls
•   dialogSubclassProc
•   PaintSolidBackground
•   PaintCustomBackground
•   CalculateTwipsPerPixel

The full code is in the module modCustomMsgBox. To say that the code is complex would be an understatement and I have no intention of explaining each part of it in this article.

Additional code is used to manage the docking of messages to specific corners of the screen. This is in the modules modMetrics and modMonitorInfo.

Although much of the code is complex, using it in your own applications is extremely easy! For example:

a)   Replicate a standard message box centred on the screen at default 100% zoom

MsgBox - Centred, 100% zoom
    MsgBoxPZ "Standard centred prompt", vbInformation + vbOKOnly, "Centred MsgBox", , , -1, -1, 100

       OR omitting the default values . . .

    MsgBoxPZ "Standard centred prompt", vbInformation + vbOKOnly, "Centred MsgBox"


b)   Message box centred on the screen at 175% zoom

MsgBox - Centred, 175% zoom
    MsgBoxPZ "Standard centred prompt" & vbCrLf & vbCrLf & "Zoom = 175%", vbInformation, "Customised Position & Zoom", , , , , 175

       OR using named Zoom argument . . .

    MsgBoxPZ "Standard centred prompt" & vbCrLf & vbCrLf & "Zoom = 175%", vbInformation, "Customised Position & Zoom", Zoom:= 175


c)   Place a message box at Left = 3000, Top = 1500 (both in twips) and 125% zoom

MsgBox - Custom Position, 125% zoom
    MsgBoxPZ "This dialog box appears at specified position with proportional zoom scaling" & vbCrLf & vbCrLf & _
        "Position: Left = 3000, Top = 1500" & vbCrLf & "Zoom = 125%", vbInformation + vbOKCancel, "Customised Position & Zoom", _
        Left:=3000, Top:=1500, Zoom:=125


d)   Position a message box at top left corner: Left = 0, Top = 0 and 150% zoom

MsgBox - Top Left, 150% zoom
    MsgBoxPZ "This dialog box is located near the top-left corner." & vbCrLf & vbCrLf & "Zoom = 150%", vbInformation, "Top-Left Corner", _
        Left:= 0, Top:= 0, Zoom:= 150


e)   Position a message box at bottom right corner with 200% zoom

MsgBox - Bottom Right, 200% zoom

    'get screen height and width to determine bottom right corner position
    Dim MSH As Long, MSW As Long
    MSH = MetricsScreenHeight()
    MSW = MetricsScreenWidth()

    MsgBoxPZ "This dialog box is located near the bottom-right corner." & vbCrLf & vbCrLf & "Zoom = 200%", vbInformation, "Bottom-Right Corner", _
        Left:= MSW, Top:= MSH, Zoom:= 200




Example App

The example app supplied with this article has a single form that allows you to test the functionality.

Main Form
NOTE: The positioning code only works reliably on the primary monitor. For that reason, several buttons are automatically disabled when Access is on a secondary monitor:

MainForm on Secondary Monitor


Download

Click to download: MsgBoxPositionZoom_v1.2      ACCDB file - approx 1 MB (zipped)

As is the case for all files downloaded from the internet, first unblock the downloaded file, unzip then save to a trusted location.
For more details, see my article: Unblock downloaded files by removing the Mark of the Web



Using the MsgBoxPZ function in your own apps

To use this function in your own apps, import the module modCustomMsgBox.
If you also want to make use of the docking functionality, also import the modules modMetrics and modMonitorInfo.

OPTIONAL: Rename the MsgBoxPZ function as MsgBox. Access will then use this custom function in place of the standard VBA MsgBox function.

Doing this will require minor alterations to the existing function code shown above (and that used in the example app) to disambiguate the references to the VBA MsgBox function.
The updated code is as follows:

' =====================================================================================
' PUBLIC FUNCTION: MsgBox (Position & Zoom) - used to overwrite the VBA MsgBox function
' =====================================================================================
Public Function MsgBox( _
ByVal Prompt As String, _
Optional ByVal Buttons As VbMsgBoxStyle = vbOKOnly, _
Optional ByVal Title As String = vbNullString, _
Optional ByVal HelpFile As String = vbNullString, _
Optional ByVal Context As Long = 0, _
Optional ByVal Left As Long = -1, _
Optional ByVal Top As Long = -1, _
Optional ByVal Zoom As Single = 100) As VbMsgBoxResult

If Title = vbNullString Then
Title = Application.Name
End If

m_TargetdialogTitle = Title
m_PromptText = Prompt
m_IsInputBox = False
m_MsgBoxIconStyle = (Buttons And &H70)
m_hCustomIcon = 0
m_hPromptEdit = 0
m_IsHeightClamped = False
m_RequiresScroll = False
m_RequiresScroll = False

' Parse zoom percentage (Single value, clamped between MIN_ZOOM_PERCENT and MAX_ZOOM_PERCENT)
Dim safeZoomPercent As Single
safeZoomPercent = ParseZoom(Zoom)
m_ZoomFactor = CDbl(safeZoomPercent) / 100

' Coordinate setup (Twips to Pixels with display DPI awareness)
If Left >= 0 And Top >= 0 Then
' If Nz(Left, -1) <> -1 And Nz(Top, -1) <> -1 Then
Dim twipsPerPixelX As Double, twipsPerPixelY As Double
CalculateTwipsPerPixel twipsPerPixelX, twipsPerPixelY
m_TargetPixelX = CLng(Left / twipsPerPixelX)
m_TargetPixelY = CLng(Top / twipsPerPixelY)
Else
m_TargetPixelX = -1
m_TargetPixelY = -1
End If

m_TimerElapsedTicks = 0
m_PrevWndProc = 0
m_hScaledFont = 0
m_SubclassedHwnd = 0
m_SplitPixelY = 0

' Always activate timer to ensure height bounds clamping and text scrolling checks occur
m_TimerHandle = SetTimer(0, TIMER_IDENTIFIER, 10, AddressOf dialogTimerProc)

' Invoke native dialog box. Disambiguate references to VBA MsgBox function
If Len(HelpFile) > 0 Then
MsgBox = VBA.MsgBox(Prompt, Buttons, Title, HelpFile, Context)
Else
MsgBox = VBA.MsgBox(Prompt, Buttons, Title)
End If

' Comprehensive cleanup of resources
CleanupHookResources
End Function


All existing MsgBox code will continue to work without any alteration, with all existing messages centred on the screen at 100% zoom as before!



Related Article

A very similar function called InputBoxPZ can be used to enhance/replace the standard InputBox function by adding the same additional positioning and zoom functionality.

See my article: Input Box with Position & Zoom



Feedback

Please use the E-Mail button in the contact form below to let me know whether you found this article useful or if you have any questions.

Please also consider making a donation towards the costs of maintaining this website. Thank you


Colin Riddington Mendip Data Systems Last Updated 28 Oct 2026




Return to Code Samples Page




Return to Top