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.
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 works only in Windows and 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.