【发布时间】:2011-01-02 13:29:41
【问题描述】:
当用户单击表单上的 X 按钮时,如何隐藏而不是关闭它?
我在FormClosing 中尝试过this.hide(),但它仍然关闭了表单。
【问题讨论】:
当用户单击表单上的 X 按钮时,如何隐藏而不是关闭它?
我在FormClosing 中尝试过this.hide(),但它仍然关闭了表单。
【问题讨论】:
像这样:
private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
Hide();
}
}
(通过Tim Huffman)
【讨论】:
e.CloseReason(查看其他答案)。否则,当系统关闭或其他事件关闭表单时,表单不会关闭。
我在之前的答案中发表了评论,但我想我会提供自己的答案。根据您的问题,此代码类似于最佳答案,但添加了另一个提到的功能:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
Hide();
}
}
如果用户只是在窗口中点击X,表单就会隐藏;如果有任何其他内容,例如任务管理器、Application.Exit() 或 Windows 关闭,则表单已正确关闭,因为将执行 return 语句。
【讨论】:
【讨论】:
如果你想使用显示/隐藏方法,我实际上已经为我最近完成的游戏菜单结构做了这个......我就是这样做的:
为您自己创建一个按钮以及您想要执行的操作,例如“下一步”按钮,并将以下代码与您的程序相匹配。对于本例中的下一个按钮,代码为:
btnNext.Enabled = true; //This enabled the button obviously
this.Hide(); //Here is where the hiding of the form will happen when the button is clicked
Form newForm = new newForm(); //This creates a new instance object for the new form
CurrentForm.Hide(); //This hides the current form where you placed the button.
这是我在游戏中使用的代码的 sn-p,可帮助您理解我要解释的内容:
private void btnInst_Click(object sender, EventArgs e)
{
btnInst.Enabled = true; //Enables the button to work
this.Hide(); // Hides the current form
Form Instructions = new Instructions(); //Instantiates a new instance form object
Instructions.Show(); //Shows the instance form created above
}
所以有一个显示/隐藏方法几行代码,而不是为这样一个简单的任务编写大量代码。 我希望这有助于解决您的问题。
【讨论】:
根据其他响应,您可以将其放入您的表单代码中:
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
Hide();
}
}
根据MSDN,首选覆盖:
OnFormClosing 方法还允许派生类处理 没有附加委托的事件。这是首选技术 用于处理派生类中的事件。
【讨论】:
请注意,在执行此操作时(已发布了几个答案),您还需要找到一种方法来允许用户在他们真正想要的时候关闭表单。如果用户在应用程序运行时试图关闭机器,这确实会成为一个问题,因为(至少在某些操作系统上)这将阻止操作系统正确或有效地关闭。
我解决此问题的方法是检查堆栈跟踪 - 用户尝试单击 X 与系统尝试结束应用程序以准备关闭时之间存在差异。
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
StackTrace trace = new StackTrace();
StackFrame frame;
bool bFoundExitCommand = false;
for (int i = 0; i < trace.FrameCount; i++)
{
frame = trace.GetFrame(i);
string methodName = frame.GetMethod().Name;
if (methodName == "miExit_Click")
{
bFoundExitCommand = true;
Log("FormClosing: Found Exit Command ({0}) - will allow exit", LogUtilityLevel.Debug3, methodName);
}
if (methodName == "PeekMessage")
{
bFoundExitCommand = true;
Log("FormClosing: Found System Shutdown ({0}) - will allow exit", LogUtilityLevel.Debug3, methodName);
}
Log("FormClosing: frame.GetMethod().Name = {0}", LogUtilityLevel.Debug4, methodName);
}
if (!bFoundExitCommand)
{
e.Cancel = true;
this.Visible = false;
}
else
{
this.Visible = false;
}
}
【讨论】:
这是模态表单的行为。当您使用form.ShowDialog() 时,您要求这种行为。这样做的原因是 form.ShowDialog 在表单被隐藏或销毁之前不会返回。所以当表单被隐藏时,form.ShowDialog里面的pump会销毁它,这样它就可以返回了。
如果你想显示和隐藏一个表单,那么你应该使用无模式对话框模型 http://msdn.microsoft.com/en-us/library/39wcs2dh(VS.80).aspx
form.Show() 立即返回,您可以随心所欲地显示和隐藏此窗口,除非您明确销毁它,否则它不会被销毁。
当您使用非模态表单的子项的非模态表单时,您还需要在循环中使用Application.Run 或Application.DoEvents 运行消息泵。如果创建表单的线程退出,那么表单将被销毁。如果该线程不运行泵,那么它拥有的表单将无响应。
编辑:这听起来像是ApplicationContext 旨在解决的问题。 http://msdn.microsoft.com/en-us/library/system.windows.forms.applicationcontext.aspx
基本上,您从 ApplicationContext 派生一个类,将 ApplicationContext 的一个实例作为参数传递给Application.Run()
// Create the MyApplicationContext, that derives from ApplicationContext,
// that manages when the application should exit.
MyApplicationContext context = new MyApplicationContext();
// Run the application with the specific context.
Application.Run(context);
您的应用程序上下文需要知道何时可以退出应用程序以及何时隐藏表单不应退出应用程序。该应用程序何时退出。您的应用程序上下文或表单可以调用应用程序上下文的ExitThread() 方法来终止消息循环。届时Application.Run() 将返回。
如果不了解表单的层次结构以及决定何时隐藏表单和何时退出的规则,就不可能更具体。
【讨论】:
Application.Run(MyAppContext)