vba code to possition a message box?

tonywatsonhelp

Well-known Member
Joined
Feb 24, 2014
Messages
3,210
Office Version
  1. 365
  2. 2019
  3. 2016
Platform
  1. Windows
Hi everyone,
does anyone know if its possible to position a message box where you want it on the screen with vba code?
at the moment my message box pops up in the middle of the screen? this is not ideal as I'd like it to the right.
I'm happy to play about with the numbers to get it into position, I was just wondering if it can be moved and if so does anyone have the code I need? I'll be able to adjust it to my requirements, I just need the code used to make it appear somewhere else on the screen?

Thanks

Tony
 

Excel Facts

Create a Pivot Table on a Map
If your data has zip codes, postal codes, or city names, select the data and use Insert, 3D Map. (Found to right of chart icons).
Hi,

I have an example that I downloaded
As an alternative I can suggest to use a UserForm

Code:
'Controlling the position of a MsgBox


'You can create a CBT hook for your application so that it receives notifications when windows are created and destroyed. If you display a message box with this CBT hook in place, your application will receive a HCBT_ACTIVATE message when the message box is activated. Once you receive this HCBT_ACTIVATE message, you can align or position the window with the SetWindowPos API function and then finally release the CBT hook. See the "Test" routine for a demonstration.


'PLACE CODE IN A STANDARD MODULE


Option Explicit


Public Enum ePosMsgBox
    eTopLeft
    eTopRight
    eTopCentre
    eBottomLeft
    eBottomRight
    eBottomCentre
    eCentreScreen
    eCentreDialog
End Enum


Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type


'Message API and constants
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal zlhHook As Long) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Private Const GWL_HINSTANCE = (-6)
Private Const SWP_NOSIZE = &H1
Private Const SWP_NOZORDER = &H4
Private Const SWP_NOACTIVATE = &H10
Private Const HCBT_ACTIVATE = 5
Private Const WH_CBT = 5


'Other APIs
Private Declare Function GetForegroundWindow Lib "user32" () As Long
Private Declare Function SystemParametersInfo Lib "user32" Alias "SystemParametersInfoA" (ByVal uAction As Long, ByVal uParam As Long, lpvParam As Any, ByVal fuWinIni As Long) As Long


Private zlhHook As Long
Private zePosition As ePosMsgBox




'Purpose   :    Displays a msgbox at a specified location on the screen
'Inputs    :    As per a standard MsgBox +
'               Position                An enumerated type which controls the screen position of the MsgBox
'Outputs   :    As per a standard Msgbox
'Notes     :


'Purpose   :    Displays a msgbox at a specified location on the screen
'Inputs    :    As per a standard MsgBox +
'               Position                An enumerated type which controls the screen position of the MsgBox
'Outputs   :    As per a standard Msgbox
'Notes     :    VB only, doesn't work in VBA


Function MsgboxEx(Prompt As String, Optional Buttons As VbMsgBoxStyle, Optional Title, Optional HelpFile, Optional Context, Optional Position As ePosMsgBox = eCentreScreen) As VbMsgBoxResult
    Dim lhInst As Long
    Dim lThread As Long


    'Set up the CBT hook
    lhInst = GetWindowLong(GetForegroundWindow, GWL_HINSTANCE)
    lThread = GetCurrentThreadId()
    zlhHook = SetWindowsHookEx(WH_CBT, AddressOf zWindowProc, lhInst, lThread)
    
    zePosition = Position
    
    'Display the message box
    MsgboxEx = MsgBox(Prompt, Buttons, Title, HelpFile, Context)
End Function


'Call back used by MsgboxEx
Private Function zWindowProc(ByVal lMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Dim tFormPos As RECT, tMsgBoxPos As RECT, tScreenWorkArea As RECT
    Dim lLeft As Long, lTop As Long
    Static sbRecursive As Boolean


    If lMsg = HCBT_ACTIVATE Then
        On Error Resume Next
        'A new dialog has been displayed
        tScreenWorkArea = ScreenWorkArea
        'Get the coordinates of the form and the message box so that
        'you can determine where the center of the form is located
        GetWindowRect GetForegroundWindow, tFormPos
        GetWindowRect wParam, tMsgBoxPos
        
        Select Case zePosition
        Case eCentreDialog
            lLeft = (tFormPos.Left + (tFormPos.Right - tFormPos.Left) / 2) - ((tMsgBoxPos.Right - tMsgBoxPos.Left) / 2)
            lTop = (tFormPos.Top + (tFormPos.Bottom - tFormPos.Top) / 2) - ((tMsgBoxPos.Bottom - tMsgBoxPos.Top) / 2)
        
        Case eCentreScreen
            lLeft = ((tScreenWorkArea.Right - tScreenWorkArea.Left) - (tMsgBoxPos.Right - tMsgBoxPos.Left)) / 2
            lTop = ((tScreenWorkArea.Bottom - tScreenWorkArea.Top) - (tMsgBoxPos.Bottom - tMsgBoxPos.Top)) / 2


        
        Case eTopLeft
            lLeft = tScreenWorkArea.Left
            lTop = tScreenWorkArea.Top
        
        Case eTopRight
            lLeft = tScreenWorkArea.Right - (tMsgBoxPos.Right - tMsgBoxPos.Left)
            lTop = tScreenWorkArea.Top
        
        Case eTopCentre
            lLeft = ((tScreenWorkArea.Right - tScreenWorkArea.Left) - (tMsgBoxPos.Right - tMsgBoxPos.Left)) / 2
            lTop = tScreenWorkArea.Top
        
        
        Case eBottomLeft
            lLeft = tScreenWorkArea.Left
            lTop = tScreenWorkArea.Bottom - (tMsgBoxPos.Bottom - tMsgBoxPos.Top)
        
        Case eBottomRight
            lLeft = tScreenWorkArea.Right - (tMsgBoxPos.Right - tMsgBoxPos.Left)
            lTop = tScreenWorkArea.Bottom - (tMsgBoxPos.Bottom - tMsgBoxPos.Top)
        
        Case eBottomCentre
            lLeft = ((tScreenWorkArea.Right - tScreenWorkArea.Left) - (tMsgBoxPos.Right - tMsgBoxPos.Left)) / 2
            lTop = tScreenWorkArea.Bottom - (tMsgBoxPos.Bottom - tMsgBoxPos.Top)
        
        End Select
        
        If lLeft < 0 And sbRecursive = False Then
            'Left handside of Msgbox is off-screen - reposition in middle of screen
            sbRecursive = True
            zePosition = eCentreScreen
            zWindowProc HCBT_ACTIVATE, wParam, lParam
            sbRecursive = False
            Exit Function
        End If


        'Position the msgbox
        SetWindowPos wParam, 0, lLeft, lTop, 10, 10, SWP_NOSIZE Or SWP_NOZORDER Or SWP_NOACTIVATE
        
        'Release the CBT hook
        UnhookWindowsHookEx zlhHook
    End If
    zWindowProc = False


End Function




'Purpose   :    Returns the screen dimensions, not including the tastbar
'Inputs    :    N/A
'Outputs   :    A type which defines the extent of the screen work area.
'Notes     :


Function ScreenWorkArea() As RECT
    Dim tScreen As RECT
    Dim lRet As Long
    Const SPI_GETWORKAREA = 48
    
    lRet = SystemParametersInfo(SPI_GETWORKAREA, vbNull, tScreen, 0)
    ScreenWorkArea = tScreen
End Function




'Demonstration routine
Sub Test()
    MsgboxEx "Hello BottomCentre", , , , , eBottomCentre
    MsgboxEx "Hello BottomLeft", , , , , eBottomLeft
    MsgboxEx "Hello BottomRight", , , , , eBottomRight
    MsgboxEx "Hello CentreDialog", , , , , eCentreDialog
    MsgboxEx "Hello CentreScreen", , , , , eCentreScreen
    MsgboxEx "Hello TopCentre", , , , , eTopCentre
    MsgboxEx "Hello TopLeft", , , , , eTopLeft
    MsgboxEx "Hello TopRight", , , , , eTopRight
End Sub
 
Upvote 0
Hi,
thats very good code and the sample works great, but my message box is not part of a module its in a sheet, and I can't get it to do anything.
maybe a user form would be better?
thanks for the advice

Tony
 
Upvote 0

Forum statistics

Threads
1,223,713
Messages
6,174,043
Members
452,542
Latest member
Bricklin

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top