解决方法
永久禁用关闭按钮的方法是为窗体的窗口类设置
CS_NOCLOSE
style.要从WinForms应用程序执行此操作,请覆盖表单的
CreateParams
property并使用|来添加SC_NOCLOSE标志.运算符,例如:
protected override CreateParams CreateParams { get { const int CS_NOCLOSE = 0x200; CreateParams cp = base.CreateParams; cp.ClassStyle = cp.ClassStyle | CS_NOCLOSE; return cp; } }
但这是一个永久的解决方案,因为您无法即时更新窗口类样式.您必须销毁并重新创建窗口类.
但是,您可以在系统菜单中禁用“关闭”命令,这也会自动禁用标题栏中的关闭按钮.
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)); } } }
请注意,这确实是一个瞬态操作.如果您执行任何导致系统菜单被框架修改的内容(例如最大化或最小化表单),您的修改将被删除.更多细节见于my related answer here.这通常是一个问题,为什么你更喜欢使用第一个解决方案.但在这种情况下,由于您想要动态禁用和重新启用,这没什么大不了的.
最后,请注意你提出的建议与Windows UI Guidelines for dialog boxes相反的事实.他们说,从本质上讲,用户希望看到一个关闭按钮,它的存在给他们一种安全感,他们可以随时安全地“走出“任何弹出的屏幕.因此,您不应该禁用它.它确实将进度对话框作为例外调用,但它继续说进度对话框应该总是有一个“取消”按钮,允许中止操作.在这种情况下,您可以简单地使标题栏中的关闭按钮调用此“取消”按钮 – 无需禁用它.