Introduction
In VBA, there are times when you need extremely high-level control, such as “temporarily disabling the ‘Close’ button (X button) at the top right of the Excel window.” This might be necessary when you want to force a specific user operation or when accidental closing of Excel during a critical process would cause problems.
Such manipulation of the Excel application window itself can be achieved by directly calling Windows API functions. In this article, I will explain a set of techniques to remove the “Close” item from the Excel window menu, gray out the X button to disable it, and then restore it.
[Important] This macro alters the fundamental behavior of Excel. If used incorrectly, you may not be able to close Excel normally. Please use it carefully and always ensure you have a method to restore the button.
VBA Sample Code to Disable/Enable the “Close” Button
Declare statements for using the API and Const (constants) must be written at the very top of the module (before any procedures like Sub).
Complete Code (API Declarations + 2 Macros)
'--- Declare API functions and constants at the top of the module ---
' Compatible with both 64-bit and 32-bit
#If VBA7 Then
Private Declare PtrSafe Function GetSystemMenu Lib "user32" (ByVal hwnd As LongPtr, ByVal bRevert As Long) As LongPtr
Private Declare PtrSafe Function DeleteMenu Lib "user32" (ByVal hMenu As LongPtr, ByVal nPosition As Long, ByVal wFlags As Long) As Long
Private Declare PtrSafe Function DrawMenuBar Lib "user32" (ByVal hwnd As LongPtr) As Long
#Else
Private Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Long, ByVal bRevert As Long) As Long
Private Declare Function DeleteMenu Lib "user32" (ByVal hMenu As Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long
Private Declare Function DrawMenuBar Lib "user32" (ByVal hwnd As Long) As Long
#End If
' Constants used in DeleteMenu
Private Const SC_CLOSE As Long = &HF060
Private Const MF_BYCOMMAND As Long = &H0
' --- Macro 1: Disable the Excel "Close" button ---
Sub DisableExcelCloseButton()
Dim hMenu As LongPtr
' 1. Get the handle to the system menu of the Excel window
hMenu = GetSystemMenu(Application.hwnd, 0&)
' 2. Delete the "Close" command from the menu
DeleteMenu hMenu, SC_CLOSE, MF_BYCOMMAND
' 3. Redraw the menu bar to apply changes
DrawMenuBar Application.hwnd
MsgBox "The 'Close' button has been disabled."
End Sub
' --- Macro 2: Restore (Enable) the disabled "Close" button ---
Sub EnableExcelCloseButton()
Dim hMenu As LongPtr
' 1. Set the second argument of GetSystemMenu to 1 to revert the system menu to its default state
hMenu = GetSystemMenu(Application.hwnd, 1&)
' 2. Redraw the menu bar to apply changes
DrawMenuBar Application.hwnd
MsgBox "The 'Close' button has been enabled."
End Sub
Explanation of the Code
DisableExcelCloseButton Macro
hMenu = GetSystemMenu(Application.hwnd, 0&)- GetSystemMenu: Retrieves the “handle” (an identifier for manipulation) to the system menu of the specified window (the menu displayed by clicking the icon at the top left of the window or right-clicking the title bar).
- Application.hwnd: The handle of the main Excel application window.
- Second argument
0&: Means the same as False. This mode retrieves the handle of the current menu.
DeleteMenu hMenu, SC_CLOSE, MF_BYCOMMAND- DeleteMenu: Deletes a specific menu item from the specified menu.
- First argument
hMenu: The handle of the menu to manipulate. - Second argument
SC_CLOSE: The ID of the menu item you want to delete.SC_CLOSEis defined in Windows as the ID for the “Close” command. - Third argument
MF_BYCOMMAND: Indicates that the second argument is a menu item ID.
DrawMenuBar Application.hwnd- DrawMenuBar: A command to redraw the menu bar of the specified window. Without executing this, the changes made by
DeleteMenuwill not be reflected on the screen.
- DrawMenuBar: A command to redraw the menu bar of the specified window. Without executing this, the changes made by
EnableExcelCloseButton Macro
hMenu = GetSystemMenu(Application.hwnd, 1&)Passing1&(True) to the second argument ofGetSystemMenutriggers a special behavior: if the menu has been modified, it resets it to its original initial state. This restores the deleted “Close” command to its previous state.
Summary
In this article, I explained how to disable and enable the “Close” button of the Excel application using Windows API.
- Get the window’s system menu with
GetSystemMenu. - Delete the “Close” command (
SC_CLOSE) withDeleteMenu. - Update the screen display with
DrawMenuBar. - To restore, call
GetSystemMenuwith the second argument set to 1.
Since this macro is very powerful, it always carries the risk that the user may not be able to exit Excel. Please design carefully, such as ensuring you provide a restoration macro like EnableExcelCloseButton and automatically enabling it in the Workbook_BeforeClose event, so as not to prevent the application from closing.
