Welcome to AddressOf.com Sign in | Join | Help

Windows Forms - Disable the Close Button

By Cory Smith

Download source code - 6.34kb

Introduction

I've seen it asked many times, “How do I disable the close button on a Windows Form, but still have the system menu, minimize and maximize available?”.  I've also seen a lot of answers to how to accomplish this.  Let's look at the answer that appears to be very popular for solving this issue.

CloseButtonRemove.vb

Option Explicit On
Option Strict
On

Imports
System.Runtime.InteropServices

Public Class CloseButtonRemove

  Private Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Integer, ByVal revert As Integer) As Integer
  Private Declare Function GetMenuItemCount Lib "user32" (ByVal menu As Integer) As
Integer
  Private Declare Function RemoveMenu Lib "user32" (ByVal menu As Integer, ByVal position As Integer, ByVal flags As Integer) As
Integer
 
Private Declare Function DrawMenuBar Lib "user32" (ByVal hwnd As Integer) As
Integer
 
Private Declare Function FormatMessageA Lib "kernel32" (ByVal flags As Integer, ByRef source As Object, ByVal messageID As Integer, ByVal languageID As Integer, ByVal buffer As String, ByVal size As Integer, ByRef arguments As Integer) As Integer

  Private Const MF_BYPOSITION As Integer = &H400
  Private Const MF_DISABLED As Integer
= &H2

  Private Sub New()
  End Sub

  Public Shared Sub Disable(ByVal form As System.Windows.Forms.Form)
   
' Get handle to system menu for the form provided.
   
Dim menu As Integer
= GetSystemMenu(form.Handle.ToInt32, 0)
   
' Get number of items in this system menu.
   
Dim count As Integer
= GetMenuItemCount(menu)
   
' Remove last item from system menu (last item should be ’Close’).
   
If RemoveMenu(menu, count - 1, MF_DISABLED Or MF_BYPOSITION) = 0
Then
     
Throw New
Exception(FormatMessage(Err.LastDllError))
   
Else
     
' On success, force a redraw of the system menu.
     
If DrawMenuBar(form.Handle.ToInt32) = 0
Then
       
Throw New
Exception(FormatMessage(Err.LastDllError))
      End
If
   
End
If
 
End Sub

  Public Shared Function FormatMessage(ByVal [error] As Integer) As String
   
Const FORMAT_MESSAGE_FROM_SYSTEM As Short
= &H1000
    Const LANG_NEUTRAL As Short
= &H0
    Dim buffer As String
= Space(999)
    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, [error], LANG_NEUTRAL, buffer, 999, 0)
    buffer = Replace(Replace(buffer, Chr(13), ""), Chr(10), "")
    Return
buffer.Substring(0, buffer.IndexOf(Chr(0)))
  End
Function

End

Class

I've attempted to document the code fully so that it's easier to see what is going on.  Also, bear in mind that most of the sample code floating around on the net doesn't take into account possible errors occuring doing this task in more of a brute force method.  Based on the SDK documentation, I've added error checking where appropriate.  Also, take note of the FormatMessage function that is included in this class.  It may come in handy when your working with other Win32 Interop functions as it will (usually) return a string version of a numeric error value.

So, you might ask, what's the problem with this code?  It does what was asked.  Actually, it doesn't.  The question was “How do I ***disable*** the close button?”; which would mean disabling the 'close' menu item as well... not deleting it from the menu.

The following code shows how to disable the close button according to the SDK documentation.

CloseButton.vb

Option Explicit On
Option Strict
On

Public

Class CloseButton

  Private Declare Function GetSystemMenu Lib "user32" (ByVal hwnd As Integer, ByVal revert As Integer) As Integer
  Private Declare Function EnableMenuItem Lib "user32" (ByVal menu As Integer, ByVal ideEnableItem As Integer, ByVal enable As Integer) As Integer

  Private Const SC_CLOSE As Integer = &HF060
  Private Const MF_BYCOMMAND As Integer
= &H0
  Private Const MF_GRAYED As Integer
= &H1
  Private Const MF_ENABLED As Integer
= &H0

  Private Sub New()
  End Sub

  Public Shared Sub Disable(ByVal form As System.Windows.Forms.Form)
    ' The return value specifies the previous state of the menu item (it is either
    ' MF_ENABLED or MF_GRAYED). 0xFFFFFFFF indicates   that the menu item does not exist.
    Select Case EnableMenuItem(GetSystemMenu(form.Handle.ToInt32, 0), SC_CLOSE, MF_BYCOMMAND Or
MF_GRAYED)
      Case
MF_ENABLED
      Case
MF_GRAYED
      Case
&HFFFFFFFF
        Throw New
Exception("The Close menu item does not exist.")
      Case
Else
    End
Select
  End
Sub

End

Class

As you can see, we now only require two API declarations.  Also, there are not LastDllError checks necessary in order to determine the error since our single call returns one of three values as described by the SDK documentation.

To use this code within your Windows Form application, just import one of the classes into your code and add the CloseButton.Disable(Me) line to your Form1_Load (as an example).  For example:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  CloseButton.Disable(Me)
End Sub

You will also need to add the following code to your form if you will be allowing the form to minimize or maximize:

Protected Overrides Sub OnSizeChanged(ByVal e As System.EventArgs)
  CloseButton.Disable(
Me)
End Sub

Thanks to EdwardA on GDN for pointing out that whenever the form is minimized or maximized, the close button becomes enabled again.  Not really sure at this point why this is, however, overriding the OnSize event will allow you to handle this issue.

[updated] - 10.31.2003 12:39PM -  Added information about using OnResize.

Published Friday, October 31, 2003 3:38 AM by CorySmith
Filed under: , ,

Comments

# Code Samples

Saturday, December 27, 2003 1:46 AM by AddressOf.com

# re: Windows Forms - Disable the Close Button

Sunday, February 1, 2004 3:53 AM by BUGS
TNX MEN!!!

# re: Windows Forms - Disable the Close Button

Thursday, June 17, 2004 1:04 PM by Greg Robinson
Perfect, how do I enable it back though?

# re: Windows Forms - Disable the Close Button

Thursday, June 17, 2004 1:39 PM by Greg Robinson
Firgured it out. Thanks for the awesome help.

# re: Windows Forms - Disable the Close Button

Monday, July 19, 2004 5:02 PM by darnell
how do you do this in c#? tnx.

# re: Windows Forms - Disable the Close Button

Thursday, July 22, 2004 10:52 AM by Manish agarwal
what does the assigned value means in the following statement(and in similar declarations):

Private Const MF_BYPOSITION As Integer = &H400

And why are we remoing the last item in,
' Remove last item from system menu (last item should be ’Close’).
If RemoveMenu(menu, count - 1, MF_DISABLED Or MF_BYPOSITION) = 0 Then
Throw New Exception(FormatMessage(Err.LastDllError))

and why this exception is not caught anywhere in the program?

It would really be helpful if u could explain Formatmessage() function in detail.

Regards
manish

# re: Windows Forms - Disable the Close Button

Tuesday, October 19, 2004 5:37 PM by Steve
Code to take care of minimized or maximized function( Protected Overrides ......),
create a problem when you set up FormStartPosition as CenterScreen in Design time (CenterScreen startup position does not work anymore).

# re: Windows Forms - Disable the Close Button

Thursday, November 18, 2004 7:15 PM by Ivy
How it can be done with C#.NET?

# re: Windows Forms - Disable the Close Button

Friday, December 24, 2004 3:55 PM by Rich
Yeah, How do you enable the close button? In my program, after you choose yes in a Msgbox, then it needs to enable it, like in MS Excel.

# re: Windows Forms - Disable the Close Button

Saturday, February 5, 2005 4:27 AM by anousheh
How can I disable the close buttom in asp.net popup window?

# re: Windows Forms - Disable the Close Button

Thursday, February 17, 2005 3:30 AM by Babu Aboobacker
Thanx man.

The sample project is working as expected during startup, but after we minimize or maximize the form, close button is getting deactivated to its normal state!

any idea ?

# re: Windows Forms - Disable the Close Button

Thursday, March 10, 2005 3:06 AM by Cory Smith
anousheh:

To my knowledge, there is no way to do this using ASP.NET.

Babu:

Please look at the end of the article about using OnSizeChanged.

# re: Windows Forms - Disable the Close Button

Friday, July 8, 2005 4:14 AM by Jim
I translated the code to C# with minor changes:

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace DisableCloseBtn
{
/// <summary>
/// This class was taken from the following web site:
///
/// http://addressof.com/blog/articles/232.aspx
///
/// Written by Cory Smith in VB. I translated it to C#
/// </summary>
public class CloseButton
{
#region Interop Code

private const int SC_CLOSE=0xF060;
private const int MF_BYCOMMAND=0x0;
private const int MF_GRAYED=0x1;
private const int MF_ENABLED=0x0;

[DllImport("user32.dll", SetLastError = true)]
private static extern int GetSystemMenu(IntPtr hWnd, int revert);

[DllImport("user32.dll", SetLastError = true)]
private static extern int EnableMenuItem(int menu, int ideEnableItem, int enable);

#endregion

public static void Disable(Form form)
{
IntPtr hWnd = form.Handle;
int SystemMenu = GetSystemMenu(hWnd,0);
int PreviousState = EnableMenuItem(SystemMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED);
if(PreviousState == -1)
throw new Exception("The close menu does not exist");
}
}
}

The Form_Load event has one line:

CloseButton.Disable(this);

To cope with the Maximize/Minimize issue, rather than override the OnSizeChanged event, I simply had the SizeChanged event call the same event handler as the Form_Load event.

Also, I discovered a much simpler way to accomplish almost the same thing, without using any Interop. The only difference is that, rather than gray out the Close command in the system menu, it does not appear at all. This was posted by TaDa at:

http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=18762

I translated this into C# also, and it seems to work just as I'd like it to.

private const int CS_NOCLOSE = 0x200;
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ClassStyle = cp.ClassStyle | CS_NOCLOSE;
return cp;
}
}

# re: Windows Forms - Disable the Close Button

Friday, July 8, 2005 7:54 PM by Duck
I searched all over the web, and found yours to be by far the easiest to understand and implement. Cory Smith...You Rock!!

# re: Windows Forms - Disable the Close Button

Thursday, August 4, 2005 5:29 PM by Pavan
is there anyway we can make the close button do something else, along with closing itself.

# re: Windows Forms - Disable the Close Button

Wednesday, September 21, 2005 8:12 AM by Kwok Wei
Hello.... I have noticed that doing a 'alt-f4' also manages to close the window. Is there a walk around to this ? Thanks :)

# re: Windows Forms - Disable the Close Button

Friday, November 11, 2005 2:26 PM by Funo
THANKS!!! Great code!

# re: Windows Forms - Disable the Close Button

Monday, November 21, 2005 10:43 PM by Dallas
Thank you to whom ever posted this code. I really appreciate it being that I worked on disabling the close button for atleast four hours. After discovering your code I had no more then ten minutes in to it:)

# re: Windows Forms - Disable the Close Button

Wednesday, January 25, 2006 3:25 PM by Steve
Thanks for a very helpful post.

# re: Windows Forms - Disable the Close Button

Wednesday, February 22, 2006 8:41 PM by bravo_kernel
Nice class m8. Maybe you can look into this: I tried changing the constant SC_CLOSE to &H030& so that I could grey out the maximize button but no luck. Is this even possible?

ps: no need pointing to the Windowstate property. I'm having problems anchoring and can't use the build in method.

# re: Windows Forms - Disable the Close Button

Tuesday, March 28, 2006 5:09 AM by anon
excellent!

easy to use

# re: Windows Forms - Disable the Close Button

Tuesday, April 11, 2006 11:42 AM by Michael G. Kish
If you want to still be able to use the CenterScreen at Design Time, just do like Jim (SizeChanged event call) but put a flag in to keep this section from firing the first time the (when the form loads). Here is what I did & it works great.

Public Class frmMain
Private _FireSW As String = "N"

Private Sub Main_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Activated

_FireSW = "Y"
End Sub


Private Sub frmMain_SizeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.SizeChanged
Dim Common As New Common

If _FireSW = "Y" Then
Common.Disable(Me)
End If
End Sub

# re: Windows Forms - Disable the Close Button

Tuesday, May 9, 2006 8:47 PM by Ghislain Mailhot
You can remove the close button by setting the ControlBox to false. But you will loose the title bar only if no text is associated to it!

# re: Windows Forms - Disable the Close Button

Tuesday, September 26, 2006 12:38 PM by Mark Ma
Thanks it is really help.

# re: Windows Forms - Disable the Close Button

Friday, August 24, 2007 5:25 AM by madhu
is it possible to disable close option in systemmenu but close button on the form should work as usual????????.i've tried on this nearly two days but unable to find? can any one help.
Anonymous comments are disabled