Turning off the Close button temporarily

I need to temporarily disable the close button (minimize and maximize).

Each fixed solution disables all buttons or simply disables the close button permanently. Is there any way to do this temporarily?

+8
source share
7 answers

The way to permanently disable the close button is to set the CS_NOCLOSE style for the form window class. To do this from a WinForms application, you override the SC_NOCLOSE form property and add the SC_NOCLOSE flag using | operator, for example:

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

This is a permanent solution, since you cannot update window class styles on the fly. You will have to destroy and recreate the window class.

However, instead, you can disable the Close command in the system menu, which also automatically disables the Close button in the title bar.

 internal static class NativeMethods { public const int SC_CLOSE = 0xF060; public const int MF_BYCOMMAND = 0; public const int MF_ENABLED = 0; public const int MF_GRAYED = 1; [DllImport("user32.dll")] public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool revert); [DllImport("user32.dll")] public static extern int EnableMenuItem(IntPtr hMenu, int IDEnableItem, int enable); } public class MyForm : Form { // ... // If "enable" is true, the close button will be enabled (the default state). // If "enable" is false, the Close button will be disabled. bool SetCloseButton(bool enable) { IntPtr hMenu = NativeMethods.GetSystemMenu(this.Handle, false); if (hMenu != IntPtr.Zero) { NativeMethods.EnableMenuItem(hMenu, NativeMethods.SC_CLOSE, NativeMethods.MF_BYCOMMAND | (enable ? NativeMethods.MF_ENABLED : NativeMethods.MF_GRAYED)); } } } 

Please note that this is really a temporary operation. If you do anything that changes the system menu using the infrastructure (for example, to maximize or minimize the form), your changes will be erased. More details in my answer here . This is usually a problem, and why you prefer to use the first solution. But in this case, since you want to dynamically disconnect and re-enable, this does not really matter.

And finally, remember that what you offer is contrary to the Windows UI guidelines for dialog boxes . In fact, they say that users expect to see the close button and that its presence gives them a sense of security, that they can always safely β€œcrawl out” of everything that appears on the screen. Therefore, you should not disable it. He causes the progress dialogue as an exception, but continues to say that the progress dialogue should always have a Cancel button that allows you to interrupt the operation. In this case, you can simply force the close button in the title bar to call this "Cancel" button - there is no need to disable it.

+10
source

Although it is possible, I have never seen it. This is simply not how the programs do it, and your program must follow well-known patterns so that users know how to use them.

If closing the program is temporarily impossible, display a message explaining why when the user is trying. This way you can present a solution ("you must first do ...") instead of simply presenting the problem ("cannot be closed").

In addition, there are several ways to close a form. You look only at one of them. Disabling one of them will leave the rest anyway, and you will want to prevent all the parameters that lead to the closure of your window, so it is best to handle the Closing event.

+1
source

The close button is disabled in the down state: If we add: MessageBoxButtons.YesNo

 DialogResult Dr = MessageBox.Show(this, "", "", MessageBoxButtons.YesNo, MessageBoxIcon.Information); 
+1
source
 isprocessing = true; form.FormClosing += new FormClosingEventHandler(form_cancel); private void form_cancel(object sender, FormClosingEventArgs e) { if (isprocessing) { e.Cancel = true; //disables the form close when processing is true } else { e.Cancel = false; //enables it later when processing is set to false at some point } } 

It worked for me

+1
source

You cannot hide it, but you can disable it:

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

Source: http://www.codeproject.com/Articles/20379/Disabling-Close-Button-on-Forms

If you absolutely need to hide it, the only way to do this is to create a borderless form, and then draw your own minimize and maximize buttons. Here is an article on how to do this: http://www.codeproject.com/Articles/42223/Easy-Customize-Title-Bar

Before considering any of these solutions, you should consider why you need it. Depending on what you are trying to do, there is probably a much better way to present the user interface to the user, except by undoing the familiar β€œX” close button.

0
source

Using the Win32 API, you can do this as follows:

 [DllImport("User32.dll")] private static extern uint GetClassLong(IntPtr hwnd, int nIndex); [DllImport("User32.dll")] private static extern uint SetClassLong(IntPtr hwnd, int nIndex, uint dwNewLong); private const int GCL_STYLE = -26; private const uint CS_NOCLOSE = 0x0200; private void Form1_Load(object sender, EventArgs e) { var style = GetClassLong(Handle, GCL_STYLE); SetClassLong(Handle, GCL_STYLE, style | CS_NOCLOSE); } 

You will need to use GetClassLong / SetClassLong to enable the CS_NOCLOSE style. Then you can delete it using the same operations, just use (style and ~ CS_NOCLOSE) in SetClassLongPtr.

Actually, you can do this in WPF applications too (yes, I know, the question is about WinForms, but maybe someone will need it):

 private void MainWindow_OnLoaded(object sender, RoutedEventArgs e) { var hwnd = new WindowInteropHelper(this).Handle; var style = GetClassLong(hwnd, GCL_STYLE); SetClassLong(hwnd, GCL_STYLE, style | CS_NOCLOSE); } 

However, you should think about what others have suggested: just show a MessageBox or another message to indicate that the user should not close the window right now.


Edit: Since the window class is only UINT, you can use the GetClassLong and SetClassLong functions instead of GetClassLongPtr and SetClassLongPtr (as MSDN says):

If you are retrieving a pointer or handle, this function has been replaced by the GetClassLongPtr function. (Pointers and descriptors are 32 bits on 32-bit Windows and 64 bits on 64-bit Windows.)

This solves the problem described by Cody Gray regarding the lack of * Ptr functions in a 32-bit OS.

0
source

As with the other answers, you work against recommendations and frameworks, but if you really need to, one job is to put the entire contents of your form in Usercontrol and then pass this between instances of forms that either have a close button, or disabled at boot.

So, when you start to disable or activate the close button, you create an instance of a new form in which the close button is switched and then passed to the link to your user control, then it plays the user control in the current form and is transferred to the new form.

You will probably get some flicker as you did. A terrible idea IMHO, but this is an "option".

0
source

Source: https://habr.com/ru/post/1200385/


All Articles