我们在做winform时会有一个非常常见的功能,比如有一个专门用来登陆的窗体,一般来说登陆的窗体点击登陆后会关闭当前登陆的这个窗体打开程序的主窗体。如果直接想的话就会写出
private void btnLogin_Click(object sender,EventArgs e)
{
this.Close();
MainForm mf = new MainForm();
mf.Show();
}
新手的一般会这么想,但是实际运行后发现当执行到this.Close()的时候整个应用程序就会结束。这是因为窗体应用程序是使用windows消息会话在当前线程运行的你当前窗体。实际上在运行winform的时候是运行的Program.cs这个启动类。
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new LoginForm());
}
当LoginForm被Close掉过后就会跳出窗体的消息循环,Main函数也执行完了程序就会被结束掉。这里就有另外一种方法就是不关闭线程启动的窗口将它隐藏然后show出其他窗口。(当你拥有多窗口时其实都是在线程窗口的基础下创建的,所以说当你关闭子窗口时程序依然按照你的逻辑在运行,但是一旦关闭线程窗口所有窗口都会被关闭如果Main方法里没有其他代码的话就会直接关闭应用程序)
private void btnLogin_Click(object sender,EventArgs e)
{
this.Hide();
MainForm mf = new MainForm();
mf.Show();
}
这时就可以实现登陆窗口的假关闭。如果你只有很少的窗口需要隐藏那还可以这样,但是如果你的程序有大量的这种操作那会非常占用内存,况且一直在内存里的话也很容易被其他恶意程序劫持从而泄露隐私。
既然程序是因为Main函数执行完后才结束的,那么我们其实可以在Program这个启动类里动手。
//这里我们写个类,类有一个静态成员用来监视线程窗口的关闭类型
public class FormHelper()
{
public static bool CloseType = false;
}
//窗体类的按钮点击事件
private void btnLogin_Click(object sender,EventArgs e)
{
FormeHelper.CloseType = true;
this.Close();
}
//在Program.cs里后面加上判断与要开启的窗口
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new LoginForm());
if(FormState.CloseType)
{
Application.Run(new MainForm());
}
}
这里CloseType用来监视登陆窗体是不是因为我登陆成功所以才关闭的,如果不是登陆成功关闭,比如点了取消按钮或者是右上角的叉叉都不会改变当前值然后Program里判断为false就不会执行其他的,应用程序就会被关闭。如果判断为true说明是登陆成功关闭的,我们不想这个时候结束应用程序而是打开程序的主窗体这个时候在执行Application.Run();里面开启一个新窗体就完美解决了。
ps:一直在弄bs今天突然要求一个cs项目,想起来以前新手时期踩过的坑,写的比较面向纯新手,可能也有些问题欢迎dalao指教。。还有知乎这个代码块为什么我第一个插入的时候是有关键字变色的,后面就没了很怪。。