Disable applications close button (The X)

In this entry we will look at how to disable the close button (The x in the upper right hand corner of the application) of an application in C#. This can come in handy when you need to do some processing when an application is being closed, and you need to control how/when it's being closed. If you read around on the internet you will undoubtedly find many solutions, the problem is most dont account for more than one way to closing an application.


If you were to just simply disable the close button (The x in the upper right hand corner of the application), that leaves several other ways for the user to close the application. When you right-click on the title bar of an application they all have a System Menu that also has a close option, so we need to remove that option as well.

Doing all this still leaves one option available for closing the application, and that is if the user presses Alt + F4, this will close the application immediately. This is probably the easiest thing to account for, simply using the Forms FormClosing event to capture this.

To disable the close button, and remove the close option from the applications System Menu, we will have to use P/Invoke, a low level access to a Windows system, to capture several events. When using P/Invoke, I prefer to keep all of that code in a separate class file, I usually name this class Base (Since we are dealing with base level events). We will be using 4 Win32 API's:



  • RemoveMenuItem: RemoveMenu is used to remove an item from a menu. If the item being removed is a sub-menu, the sub-menu is not actually destroyed by this function, instead, the close option is simply removed from the menu.

  • GetSystemMenu: GetSystemMenu is used to obtains a handle to a window's system menu. This menu is what appears when the application icon on the title bar is clicked, or when the title bar itself is right-clicked.

  • GetMenuItemCount: GetMenuItemCount counts the number of items in a menu. Remember, the position indexes of menu items are zero based. This means that if there are n items in the menu, their position indexes go from 0 to n - 1.

  • DrawMenuBar: DrawMenuBar is used to redraw the system menu so the user can see & use it.


 

public class Base
{

        [DllImport("user32")]

        public static extern int RemoveMenu(IntPtr systemMenu, int itemPosition, int flag);


        [DllImport("user32")]

        public static extern IntPtr GetSystemMenu(IntPtr systemMenu, int revert);


        [DllImport("user32")]

        public static extern int GetMenuItemCount(IntPtr systemMenu);


        [DllImport("user32")]

        public static extern int DrawMenuBar(IntPtr currentWindow);
}


Now that we have our Base class defined with the API Calls we need, we can concentrate on the methods for removing the Close option from the system menu. This method, we'll name it DisableClose, will use the 4 API methods we declared in the Base class to retrieve the system menu, get a count of all the items in the system menu, remove the items we specify, then redraw the menu. Remember, Close is always the last item in the system menu, and thats the one we want to remove.



private void DisableClose(IntPtr window)
{

        //get the system menu of the application

        IntPtr menu = Base.GetSystemMenu(window, 0);


        //get the count of menu items in the system menu

        int count = Base.GetMenuItemCount(menu);


        //disable the "Close" command in the menu

        Base.RemoveMenu(menu, count - 1, MF_DISABLED | MF_BYPOSITION);


        //now draw the menu bar on the application

        Base.DrawMenuBar(window);
}


To remove only the "Close" option we get the count of all items in the menu, then we go to the last one, back up one (the count is zero based, so its always n-1 for the one you want) then we call the RemoveMenu API method to remove that specific item. Now when your application runs, if you right-click on the title bar to bring up the system menu, the Close option is now gone.

We have no tackled 2 of the 3 ways to close an application, the last way is if the user presses Alt + F4. To do this we will capture this in the FormClosing event of the form. We will also give them an option to either let the application close or keep it open in case they have changes they wish to save before exiting.



private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{

        //set the variable to the messagebox results

        DialogResult result =

                MessageBox.Show("Are you sure you want to exit this application",

                "Exit Application?",

                MessageBoxButtons.OKCancel,

                MessageBoxIcon.Question,

                MessageBoxDefaultButton.Button2);


        e.Cancel = (result == DialogResult.OK) ? false : true;
}


We then call DisableClose in the form's Load Event, passing it the Handle of the form like so:



private void Form1_Load(object sender, EventArgs e)
{

        DisableClose(this.Handle);
}


That's it, that's how you can disable the close button (the X) and remove the close option from the applications system menu.



No comments:

Post a Comment