[Excel VBA] How to Disable the “Close” Button (X) in Excel (Windows API)

目次

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

  1. 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.
  2. 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_CLOSE is defined in Windows as the ID for the “Close” command.
    • Third argument MF_BYCOMMAND: Indicates that the second argument is a menu item ID.
  3. DrawMenuBar Application.hwnd
    • DrawMenuBar: A command to redraw the menu bar of the specified window. Without executing this, the changes made by DeleteMenu will not be reflected on the screen.

EnableExcelCloseButton Macro

  • hMenu = GetSystemMenu(Application.hwnd, 1&) Passing 1& (True) to the second argument of GetSystemMenu triggers 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.

  1. Get the window’s system menu with GetSystemMenu.
  2. Delete the “Close” command (SC_CLOSE) with DeleteMenu.
  3. Update the screen display with DrawMenuBar.
  4. To restore, call GetSystemMenu with 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.

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次