change language:

Sometimes it may be desirable to disable the close button [X] on a userform in Excel or Word. For example, with a form where the user always has to fill in something before it can be closed or with a form with a progress bar. There may also be an aesthetic reason to hide the close button.

remove close button from form

What often happens in practice is to disable the operation of the close button using the UserForm_QueryClose event. This can be done as follows, for example:

Private Sub Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    If CloseMode = 0 Then
        Cancel = True
        MsgBox "The close button [X] is disabled.", vbCritical, "Close button disabled"
    End If
End Sub

This works in itself, but in terms of user experience this is of course not good. Users click the close button and are then notified that this is not possible. It is better to hide the close button so that users do not have the option to click the close button.

By default you cannot disable the close button in a form, but it is possible using Windows API calls. To do this, put the code below in a separate module:

Private Const GWL_STYLE As Long = -16
Private Const WS_SYSMENU As Long = &H80000

#If VBA7 Then
    Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
    #If Win64 Then
        Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr
        Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongPtrA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
    #Else
        Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long) As LongPtr
        Private Declare PtrSafe Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As LongPtr, ByVal nIndex As Long, ByVal dwNewLong As LongPtr) As LongPtr
    #End If
#Else
    Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
    Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
#End If

Public Sub RemoveCloseButton(frm As Object)
    #If VBA7 Then
        Dim lStyle As LongPtr, lFrmHandle As LongPtr
    #Else
        Dim lStyle As Long, lFrmHandle As Long
    #End If
    lFrmHandle = FindWindow("ThunderDFrame", frm.Caption)
    lStyle = GetWindowLong(lFrmHandle, GWL_STYLE)
    lStyle = lStyle And Not WS_SYSMENU
    SetWindowLong lFrmHandle, GWL_STYLE, lStyle
End Sub

You can use this in a userform in the UserForm_Initialize or UserForm_Activate event:

Private Sub UserForm_Initialize()
    RemoveCloseButton Me
End Sub

If while opening a form the caption of the form is dynamically changed using VBA, this call must be placed after this change.

Make sure that there is a button on the form with which the form can be closed, before the close button is hidden. Otherwise the form can no longer be closed.

This code also works in 64 bit Office versions.

Questions / suggestions

Hopefully, this article helped you remove the close button from a VBA Userform. If you have any questions about this topic or suggestions for improvement, please post a comment below.

arrow_up