locked
A form that cannot be closed RRS feed

  • Question

  • Hi all,

    I am making an application that I really don't want the user to be able to close the application be clicking the red 'X' on the upper right hand side of the window. Instead I want them to be able to only exit from a drop down menu (ie File --> Close). Can anyone please tell me how to accomplish this? Thanks.
    Tuesday, June 17, 2008 9:38 PM

Answers

  • Try this: This disables the X and disables it when they try to right click on the form to close.

    using System;
    using
    System.Collections.Generic;
    using
    System.ComponentModel;
    using
    System.Data;
    using
    System.Drawing;
    using
    System.Text;
    using
    System.Windows.Forms;
    using System.Runtime.InteropServices;

    namespace WindowsApplication1
    {
        public partial class Form1 :
    Form
       {
            [
    DllImport("user32.dll")]
            static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint
    uEnable);
            [
    DllImport("user32.dll")]
            static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
            internal const UInt32 SC_CLOSE = 0xF060;
            internal const UInt32 MF_ENABLED = 0x00000000;
            internal const UInt32 MF_GRAYED = 0x00000001;
            internal const UInt32 MF_DISABLED = 0x00000002;
            internal const uint MF_BYCOMMAND = 0x00000000;

            public Form1()
            {
                 InitializeComponent();
                 EnableCloseButton(
    this, false);
            }

           private void button1_Click(object sender, EventArgs e)
           {
               Application.Exit();
           }

          public static void EnableCloseButton(IWin32Window window, bool bEnabled)
          {
              IntPtr hSystemMenu = GetSystemMenu(window.Handle, false);
              EnableMenuItem(hSystemMenu, SC_CLOSE, (
    uint)(MF_ENABLED | (bEnabled ? MF_ENABLED : MF_GRAYED)));
          }



    }

    }


    John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com
    • Edited by JohnGrove Tuesday, June 17, 2008 11:56 PM Update
    • Proposed as answer by JohnGrove Wednesday, June 18, 2008 12:03 AM
    • Marked as answer by jack 321 Friday, June 20, 2008 7:59 AM
    Tuesday, June 17, 2008 11:54 PM
  • GGCO said:

    One more thing....The error says, "EnableCloseButton does not exist in the current context"

    Even when I put another item such as button1 in the place of EnableCloseButton it gives me the same error.

    EnableCloseButton is a static function in John's code snippet above. Looks like you did not put that in yet.


    http://blog.voidnish.com
    • Marked as answer by jack 321 Friday, June 20, 2008 8:00 AM
    Wednesday, June 18, 2008 2:09 PM

All replies

  • Subscribe to the FormClosing event of the form and cancel if it it was trigger by clicking on 'X'. You can also remove X by using ControlBox property

    MCTS, CodeProject MVP 2008
    Tuesday, June 17, 2008 9:53 PM
  • Add bool variable on Form level like:

    bool _CanExit;

    On menuExit click event you will set this variable to true;

    In FormClosing event handler, you will check this variable and if is not click you will cancel form closing:

    if (!_CanExit)
    {
         e.Cancel = true;
    }
    MCDBA, MCSD, MCITP http://sharpsource.blogspot.com/
    Tuesday, June 17, 2008 10:01 PM
  • Try this: This disables the X and disables it when they try to right click on the form to close.

    using System;
    using
    System.Collections.Generic;
    using
    System.ComponentModel;
    using
    System.Data;
    using
    System.Drawing;
    using
    System.Text;
    using
    System.Windows.Forms;
    using System.Runtime.InteropServices;

    namespace WindowsApplication1
    {
        public partial class Form1 :
    Form
       {
            [
    DllImport("user32.dll")]
            static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint
    uEnable);
            [
    DllImport("user32.dll")]
            static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
            internal const UInt32 SC_CLOSE = 0xF060;
            internal const UInt32 MF_ENABLED = 0x00000000;
            internal const UInt32 MF_GRAYED = 0x00000001;
            internal const UInt32 MF_DISABLED = 0x00000002;
            internal const uint MF_BYCOMMAND = 0x00000000;

            public Form1()
            {
                 InitializeComponent();
                 EnableCloseButton(
    this, false);
            }

           private void button1_Click(object sender, EventArgs e)
           {
               Application.Exit();
           }

          public static void EnableCloseButton(IWin32Window window, bool bEnabled)
          {
              IntPtr hSystemMenu = GetSystemMenu(window.Handle, false);
              EnableMenuItem(hSystemMenu, SC_CLOSE, (
    uint)(MF_ENABLED | (bEnabled ? MF_ENABLED : MF_GRAYED)));
          }



    }

    }


    John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com
    • Edited by JohnGrove Tuesday, June 17, 2008 11:56 PM Update
    • Proposed as answer by JohnGrove Wednesday, June 18, 2008 12:03 AM
    • Marked as answer by jack 321 Friday, June 20, 2008 7:59 AM
    Tuesday, June 17, 2008 11:54 PM
  • John,

    Thank you very much. The only trouble that I am running into is:

    public Form1()
            {
                 InitializeComponent();
                 EnableCloseButton(
    this, false);  // <-- this part
            }

    I know it is very basic, but should EnableCloseButton be an actual button on my form? Um..I probably will figure it out soon enough. Thanks, and any other suggestions are welcome.


    Wednesday, June 18, 2008 1:57 PM
  • One more thing....The error says, "EnableCloseButton does not exist in the current context"

    Even when I put another item such as button1 in the place of EnableCloseButton it gives me the same error.
    Wednesday, June 18, 2008 1:59 PM
  • GGCO said:

    One more thing....The error says, "EnableCloseButton does not exist in the current context"

    Even when I put another item such as button1 in the place of EnableCloseButton it gives me the same error.

    EnableCloseButton is a static function in John's code snippet above. Looks like you did not put that in yet.


    http://blog.voidnish.com
    • Marked as answer by jack 321 Friday, June 20, 2008 8:00 AM
    Wednesday, June 18, 2008 2:09 PM
  • John or anyone else, do you know how to disable the close button on the Console?

    Thanks.
    AlexB
    Wednesday, June 18, 2008 2:46 PM
  •  This is how I block my forms from being closed by that button:
    private void pushSTOP_Click ( object sender, EventArgs e )  
            {  
                this.unBlockAction = false;  
                this.Close ( );  
            }                                              // pushSTOP_Click  
     
            override protected void OnClosing ( CancelEventArgs ee )  
            {  
                if ( this.unBlockAction == false )  
                {  
                    ee.Cancel = false;  
                }  
                else  
                {  
                    ee.Cancel = true;  
                }  
            }                                              //  OnClosing 
    this.unBlockAction  is a boolean variable at the class level.

    pushSTOP is the button that closes the form.

    AlexB
    Wednesday, June 18, 2008 2:52 PM
  • It is called that because X is a button (Call it whatever you want, it calls the Win32API). Note this will also disable the close when you right click on the top of your form, so make sure you have a close button that calls Application.Exit()




    John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com
    • Edited by JohnGrove Wednesday, June 18, 2008 4:18 PM update
    Wednesday, June 18, 2008 4:17 PM
  • Alex, I can certainly find out how to do that with the Console. You can also change the Console title bar as well with the Win32 API
    John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com
    Wednesday, June 18, 2008 4:20 PM
  • Go to this site and get the .NET add in for free, you will learn tons about Win32

    http://www.pinvoke.net/
    John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com
    Wednesday, June 18, 2008 4:22 PM
  • I know how to change the Console title. I have this code and use it all the time. I need to block it from being closed manually by oversight since I frequently press buttons before I think.
    AlexB
    Wednesday, June 18, 2008 4:24 PM
  • I am aware of that site, John. It takes time to investigate. Also I went thu it all at least twice. I could not find any methods or constants related to it.
    AlexB
    Wednesday, June 18, 2008 4:26 PM
  • JohnGrove and Nishant Sivakumar,

    Thank you both! My problem is solved. Thanks alot!
    Wednesday, June 18, 2008 4:43 PM
  • Here is how you do it to a Console window:

    using System;
    using
    System.Windows.Forms;
    using
    System.Runtime.InteropServices;
    namespace
    ConsoleApplication1
    {
        class
    Program
        {
              [
    DllImport("user32.dll"
    )]
              static extern bool EnableMenuItem(IntPtr hMenu, uint uIDEnableItem, uint
    uEnable);
              [
    DllImport("user32.dll")]
              static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
              internal const UInt32 SC_CLOSE = 0xF060;
              internal const UInt32 MF_ENABLED = 0x00000000;
              internal const UInt32 MF_GRAYED = 0x00000001;
              internal const UInt32 MF_DISABLED = 0x00000002;
              internal const uint MF_BYCOMMAND = 0x00000000;
              [
    DllImport("kernel32.dll")]
              static extern IntPtr GetConsoleWindow();

              static void Main(string[] args)
             {
                   EnableCloseButton(GetConsoleWindow(),
    false);
                   Console.WriteLine("Press x to close");
                   if (Console.ReadLine() == "x")
                   {
                        return;
                   }
             }

             public static void EnableCloseButton(IntPtr window, bool bEnabled)
             {
                  IntPtr hSystemMenu = GetSystemMenu(GetConsoleWindow(), false);
                  EnableMenuItem(hSystemMenu, SC_CLOSE, (
    uint)(MF_ENABLED | (bEnabled ? MF_ENABLED : MF_GRAYED)));
             }
        }

    }


    John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com
    Wednesday, June 18, 2008 4:46 PM
  • Can we close this thread now?
    John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com
    Wednesday, June 18, 2008 9:25 PM
  • JohnGrove said:

    Can we close this thread now?


    John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com


    Oh, John, you are a genius. If it is what I have in mind that's great. Thank you.

    Yep, It appears exactly what I wanted for so long. I posted this request in the past two times and never got an answer.

    AlexB
    Wednesday, June 18, 2008 11:07 PM