Disable Window Close Button

stu_c

Registered User.
Local time
Today, 17:07
Joined
Sep 20, 2007
Messages
493
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:
It is easy enough to disable the close as others have posted.

I'm going to ask the stupid question - WHY do you need to disable the close button? Is it because you are not validating your data correctly? Because, if you are doing proper validation using every form's BeforeUpdate event, no unvalidated data will ever be saved so what does it actually matter if you remove the offensive X thereby forcing the user to use the ultimate power of task manager to close the app anyway. Since there is no way to actually prevent a user from closing an Access app, maybe you need to step back and think about my question.
 
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:
However, I assume you want to ensure users close the app from one of your forms in order to ensure certain code runs before closedown.
Access closes forms in the inverse order in which they were opened. If you have code that needs to run when the app closes, put it in the form that opens when the app opens like a login or switchboard. Then when the user logs in, don't close the login form, hide it. It will stay resident and be the last form that closes. Or if the code is in your menu/switchboard, hide that form when you open other forms.

In most apps, my first form is one that checks the links to the BE as well as the version to make sure that the FE/BE are in sync. If the links and version are OK, it hides itself and opens the login form if the app has one. The login hides itself and opens the switchboard.
 
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.
 
Thanks @isladogs your article on controlling the interface is excellent. However, we have no idea why the op wants to disable the X and I'm pretty sure we never will, so I was just completing the description of why he doesn't have to. He still may want to but that is a different thing than having to get rid of it.

Understanding form level events gives most people sufficient control for handling in-house applications. If you are creating an application that will be sold to the public, then you need to go the extra mile to do whatever you can to secure your intellectual property. When you build the app for your employer, you don't own it, your employer owns it so it is not your intellectual property so unless your employer tells you to expend extra effort, you are simply spending your employer's money unnecessarily.
 
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.
 
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
As I suspected.

Here is a link to two videos I made. They may be over your head but you have to start somewhere and in my opinion, the Form's BeforeUpdate event is the most important of all the form events. It is the LAST event that runs before Access attempts to save a dirty record and you CANNOT prevent it from running short of pulling the power plug. But, if you pull the power plug, the dirty record won't get saved anyway:) By putting your validation in this event, you can prevent the user from accidentally saving when he didn't mean to.

Remember, Access takes caring for your data personally and it makes every effort to not lose anything your user typed. That is why, Access ALWAYS attempts to save a dirty record when you close a form or do certain other things that make the dirty record lose focus. It is much harder as newcomers soon find out to stop Access from saving data than to actually save it:) The form's BeforeUpdate is the key to the whole issue. In this event, you validate data. You ensure that required fields are not empty. You ensure that dates make sense. 1/17/223 is a valid date as far as Access is concerned but certainly not logical from the perspective of your application, unless of course your app id dealing with ancient history rather than today's date. A DOB can't be in the future and neither can a DOD unless you are a fortuneteller. Very few people earn 10000 per week. So, maybe you need range checks on salary data. Very few things are free so maybe you at least want to ask the user if 0 is a valid price for a new car. It may very well be but it is certainly questionable.

 
@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 need to prevent user closing the database
For what reason would you ever "need" to prevent the application from closing except to protect data?
If users make a mistake and click on X button of the database (while he wants to close other applications) everything is gone.
Maybe, just maybe, you need code in the form's BeforeUpdate event to prevent the form from closing if it is incomplete. What happens if there is a power outage while this process is going on? What if someone spills orange juice on the keyboard? If the user just loses something he typed, then maybe he should pay a little more attention. 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. So, you protect the things that need protecting and the ripple effect protects the other stuff.
 
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.
 
We cannot forget that there are no update events on an unbound form,
And the before update won't be triggered if the form is not dirty.
At last someone understood me and the form is empty.
 

Users who are viewing this thread

Back
Top Bottom