Disable Window Close Button

stu_c

Registered User.
Local time
Today, 10:28
Joined
Sep 20, 2007
Messages
494
Hi all
on my database I have macro buttons to close tabs etc, is there a way to disable the main window close 'X' button for the whole of the access database?
 
As far as I know there is no way to disable this close button.

To prevent the application from closing unchecked, you can use the following:
1) When you start the application, you open a hidden form. It is therefore hidden so that the user cannot manipulate it.
2) At the same time, a flag (public Boolean variable bNoClose) is set to true. Alternatively a property (Let, Get, member variable)
3) In the case that is allowed to be closed, the flag is set to false.
4) There is no separate event in Access for closing the application. Therefore, the Form_Unload of the hidden form is used to check the status of bNoClose and aborts there if necessary.
 
Last edited:
Access won't do it, but you can call a Windows API routine to do it.


This comes from an Excel site, but VBA works the same for Access and Excel so this might help. It has three options, but the first one might not be adequate. The other two methods in that link make one or the other of a couple of possible WinAPI calls. Be sure to read the discussion in that link regarding the wisdom of such an action, since it potentially makes an unkillable zombie process if something goes wrong with your preferred method to actually kill your app.
 
Hi all
on my database I have macro buttons to close tabs etc, is there a way to disable the main window close 'X' button for the whole of the access database?
You can disable the close button (x on the right top of the application) with this code:

I actually used it several years ago.

Code:
#If Win64 Then
    Private Declare PtrSafe Function GetSystemMenu Lib "USER32" (ByVal hWnd As Long, ByVal wRevert As Long) As Long
    Private Declare PtrSafe Function EnableMenuItem Lib "USER32" (ByVal hMenu As Long, ByVal wIDEnableItem As Long, ByVal wEnable As Long) As Long
#Else
    Private Declare Function GetSystemMenu Lib "USER32" (ByVal hWnd As Long, ByVal wRevert As Long) As Long
    Private Declare Function EnableMenuItem Lib "USER32" (ByVal hMenu As Long, ByVal wIDEnableItem As Long, ByVal wEnable As Long) As Long
#End If


Public Sub AccessCloseButtonEnabled(pfEnabled As Boolean)
  
    ' Comments: Control the Access close button.
    '           Disabling it forces the user to exit within the application
    ' Params  : pfEnabled       TRUE enables the close button, FALSE disabled it
    ' Owner   : Copyright (c) 2008-2011 from FMS, Inc.
    ' Source  : Total Visual SourceBook
    ' Usage   : Permission granted to subscribers of the FMS Newsletter
    ' Reference http://www.fmsinc.com/microsoftaccess/startup/preventclose.asp
  
  On Error Resume Next

  Const clngMF_ByCommand As Long = &H0&
  Const clngMF_Grayed As Long = &H1&
  Const clngSC_Close As Long = &HF060&

  Dim lngWindow As Long
  Dim lngMenu As Long
  Dim lngFlags As Long

  lngWindow = Application.hWndAccessApp
  lngMenu = GetSystemMenu(lngWindow, 0)
  If pfEnabled Then
    lngFlags = clngMF_ByCommand And Not clngMF_Grayed
  Else
    lngFlags = clngMF_ByCommand Or clngMF_Grayed
  End If
  Call EnableMenuItem(lngMenu, clngSC_Close, lngFlags)
End Sub


To disable the X button, run this :
AccessCloseButtonEnabled Flase

To enable it again :
AccessCloseButtonEnabled True
 
Last edited:
I agree totally with Pat's comments.
However, I assume the OP wants to ensure users close the app from one of his/her forms in order to ensure certain code runs before closedown.

Although the FMS code that @KitaYama provided works, there are simpler ways of doing this including
1. Remove the application interface completely so your forms are 'floating on the desktop'
2. Remove the title bar buttons from your forms (no code or APIs needed). You need to use a maximized popup form and overlapping windows
Both of these methods are explained/demonstrated in my article
 
Last edited:
Just for clarity, my post was meant to be directed to the OP.
Whilst I normally do the same as Pat, I'm just pointing out other solutions to the original question.
 
All, i have adopted the technique @stu_c purports. I disable the access close button to ensure that the user closes the application from the main menu. Otherwise they could have another form open, but hit the access close button which i thought was not exiting in the preferred way by leaving access to close any open forms upon application close. @Pat Hartman , you stated that you should use the 'before update'event to validate data. Could you please explain more.

As a keen novice i'm only too happy to learn better techniques. I'd suggest the OP could probably learn something from this too.
 
@Pat Hartman I understand what you explained and how BeforeUpdate event can help, and possibly OP is better to follow your advice.
But please don't forget, there are situations where a developer may need what OP has requested and BeforeUpdate is useless. What about if the form is not a form to update/edit/add data entered by user, and you need to prevent user closing the database? Does BeforeUpdate comes even near being useful?

We were in such a situation and the above code was what we used. We could go through what @isladogs in #6 suggested, but 1-We weren't as intelligent as him. 2-And even if we were, we needed the ribbon to allow users do other actions while a certain form needed to be kept open.

I can go and write two pages and explain our situation, but I really find it too hard for you to understand the procedures we had to go through. In short, the operator opens a form, reads a barcode on order sheet. The database reads a special file (based on the barcode) and sends it to a manufacturing machine. The form and the database MUST be waiting until the machine response with a log file. There are a lot of data in the log file (list of tools, material, etc) that should be registered in a table. If users make a mistake and click on X button of the database (while he wants to close other applications) everything is gone.
 
Last edited:
You can disable the close button (x on the right top of the application) with this code:

I actually used it several years ago.

Code:
#If Win64 Then
    Private Declare PtrSafe Function GetSystemMenu Lib "USER32" (ByVal hWnd As Long, ByVal wRevert As Long) As Long
    Private Declare PtrSafe Function EnableMenuItem Lib "USER32" (ByVal hMenu As Long, ByVal wIDEnableItem As Long, ByVal wEnable As Long) As Long
#Else
    Private Declare Function GetSystemMenu Lib "USER32" (ByVal hWnd As Long, ByVal wRevert As Long) As Long
    Private Declare Function EnableMenuItem Lib "USER32" (ByVal hMenu As Long, ByVal wIDEnableItem As Long, ByVal wEnable As Long) As Long
#End If


Public Sub AccessCloseButtonEnabled(pfEnabled As Boolean)
 
    ' Comments: Control the Access close button.
    '           Disabling it forces the user to exit within the application
    ' Params  : pfEnabled       TRUE enables the close button, FALSE disabled it
    ' Owner   : Copyright (c) 2008-2011 from FMS, Inc.
    ' Source  : Total Visual SourceBook
    ' Usage   : Permission granted to subscribers of the FMS Newsletter
    ' Reference http://www.fmsinc.com/microsoftaccess/startup/preventclose.asp
 
  On Error Resume Next

  Const clngMF_ByCommand As Long = &H0&
  Const clngMF_Grayed As Long = &H1&
  Const clngSC_Close As Long = &HF060&

  Dim lngWindow As Long
  Dim lngMenu As Long
  Dim lngFlags As Long

  lngWindow = Application.hWndAccessApp
  lngMenu = GetSystemMenu(lngWindow, 0)
  If pfEnabled Then
    lngFlags = clngMF_ByCommand And Not clngMF_Grayed
  Else
    lngFlags = clngMF_ByCommand Or clngMF_Grayed
  End If
  Call EnableMenuItem(lngMenu, clngSC_Close, lngFlags)
End Sub


To disable the X button, run this :
AccessCloseButtonEnabled Flase

To enable it again :
AccessCloseButtonEnabled True
You forgot to read the copyright text?
 
For what reason would you ever "need" to prevent the application from closing except to protect data?
@Pat Hartman I don't think you ever read what I posted. And if you did, you didn't understand the situation. Maybe because of my English.
There's no data in the form. The form is waiting for the data to come. And while waiting, we don't want anybody to close the form and interupt what's going on behind the scene.

What happens if there is a power outage while this process is going on? What if someone spills orange juice on the keyboard?
Do you mean don't try to do what I have in my power because every 100 years there may be a power shortage? I do what I can do, and if there was a power shortage, then that's that.

When you prevent the form from closing because it is incomplete or has an error, you can also prevent the form from unloading and that will prevent the database from closing.
Again you're not listening. The form IS NOT INCOMPLETE. The form is empty and has nothing. The form is just waiting for a log file to come in.
 
When you prevent the form from closing because it is incomplete or has an error, you can also prevent the form from unloading and that will prevent the database from closing.
That was also the motivation for my thoughts in #2. Which form exactly controls my NoClose flag would of course depend on a specific use case.

My additional motivation for the hidden form mentioned was to have an application close event to eliminate self-created external temporary files.

I'm less interested in the close button. You can also close a lot with ALT+F4, you would have to catch that too, and probably a lot more.
 
i have made an application where with the runtime version (menu hidden) the close button was pressed when closing a report in preview. I made a hidden form, with a msgbox on unload event.


Private Sub Form_Unload(Cancel As Integer)
If MsgBox("Do you want to close the database?" & vbCrLf & vbCrLf & _
"(You can close report with Esc key)", vbYesNo) = vbNo Then
Cancel = True
End If

End Sub
 
Last edited:
We cannot forget that there are no update events on an unbound form, and yet one can use such a form to trigger certain sequences of events. When the form is a sequencer/control panel then the BeforeUpdate event might not even exist. We can argue the merits of such a design but in the end analysis, if the form is mirroring or facilitating actual business practices, we cannot second-guess the user.

On the other hand if it IS a bound form, then Pat is absolutely right that the BeforeUpdate event is the stepping-stone to achieve data integrity.
 
The OP will go away happy because he thinks he stopped Access from closing until the method fails due to something beyond his control. Users do some seriously stupid things.

Which is why I included the comment when I posted the links regarding that he should read the WHOLE ARTICLE, which had a lengthy discussion about the wisdom of the "disable the X" operation. Pat, you and I agree that the design seems somehow "off" and probably is unwise, but in the final analysis, sometimes the little birds have to fly from the nest on their own - without a net - learning that the fall from that height is painful. Besides, I really don't like the "nurturing the little birds" analogy that much because it would imply that I eat worms. Yecchh! Vermicelli, maybe. Worms? Nope.
 
I've never disabled the close operation (which I think might need more than just hiding the X - to handle shortcuts), but I do use a method in line with the nav/hidden form approach mentioned by several here to present users an "are you sure?" so they don't accidentally close and get frustrated having to reopen (for example, if just trying to move the window).

In the world of Access, hoping your DB never closes unexpectedly is a rather risky approach to managing data integrity...
 
I actually preferred to use the method of catching the Unload event, which can be canceled. If you cancel the Unload, clicking that X doesn't matter. Oh, sure, the user can step out to the desktop, run Task Manager, and close the app - but at least in that case you know that is what the user really wanted to do, despite the barriers you tossed in the way.

Of course, I always popped up a message box in that case, explaining that you can't close the form while it is still dirty, and further advising that you could use the command buttons built into the form, to Save or Cancel what you were doing, after which that X would work normally. Or you could use the Close button on that form and then on the parent. Far easier mechanically. All it took was a matter of user education. And if the form wasn't dirty, its upper-right X WOULD work. As would the dispatcher form's X.
 
save button
This has not yet been discussed, but it is suitable to continue the discussion with a further 13 contributions and to increase the "popularity" of the topic.
 

Users who are viewing this thread

Back
Top Bottom