C# .NET启动屏幕问题

C# .NET启动屏幕问题,c#,.net,splash-screen,C#,.net,Splash Screen,我有一个通过显示的事件调用的C#数据库应用程序的启动屏幕。启动屏幕包含一些在调用主窗体的构造函数时被预处理的信息,因此我使用显示的事件,因为这些信息应该是可用的 但是,当显示启动屏幕时,主窗体变白,菜单栏、底部菜单栏甚至灰色背景都是白色且不可见的。看起来程序挂起了,但在我内置的5秒延迟后,横幅消失,程序正常显示。另外,在横幅上,我有一些在启动屏幕显示时不显示的标签 这是我的代码,解释一下为什么它不起作用会有很大帮助 启动屏幕代码: public partial class StartupBann

我有一个通过显示的事件调用的C#数据库应用程序的启动屏幕。启动屏幕包含一些在调用主窗体的构造函数时被预处理的信息,因此我使用显示的事件,因为这些信息应该是可用的

但是,当显示启动屏幕时,主窗体变白,菜单栏、底部菜单栏甚至灰色背景都是白色且不可见的。看起来程序挂起了,但在我内置的5秒延迟后,横幅消失,程序正常显示。另外,在横幅上,我有一些在启动屏幕显示时不显示的标签

这是我的代码,解释一下为什么它不起作用会有很大帮助

启动屏幕代码:

public partial class StartupBanner : Form
{
    public StartupBanner(int missingNum, int expiredNum)
    {
        InitializeComponent();
        missingLabel.Text = missingNum.ToString() + " MISSING POLICIES";
        expiredLabel.Text = expiredNum.ToString() + " EXPIRED POLICIES";
    }
}
    private void MainForm_Shown(object sender, EventArgs e)
    {
        StartupBanner startup = new StartupBanner(missingPoliciesNum, expiredPoliciesNum);
        startup.MdiParent = this;
        startup.Show();

        Thread.Sleep(5000);
        startup.Close();
    }
呼叫代码:

public partial class StartupBanner : Form
{
    public StartupBanner(int missingNum, int expiredNum)
    {
        InitializeComponent();
        missingLabel.Text = missingNum.ToString() + " MISSING POLICIES";
        expiredLabel.Text = expiredNum.ToString() + " EXPIRED POLICIES";
    }
}
    private void MainForm_Shown(object sender, EventArgs e)
    {
        StartupBanner startup = new StartupBanner(missingPoliciesNum, expiredPoliciesNum);
        startup.MdiParent = this;
        startup.Show();

        Thread.Sleep(5000);
        startup.Close();
    }

使用startup.ShowDialog()在启动屏幕上显示正确的标签信息,但这会锁定应用程序,我需要在大约5秒钟后使启动消失,这就是为什么它是启动。;)

首先使用ShowDialog()而不是Show()运行启动屏幕,以便启动屏幕锁定主窗体而不锁定主线程:

private void MainForm_Shown(object sender, EventArgs e)
{
    StartupBanner startup = new StartupBanner(missingPoliciesNum, expiredPoliciesNum);
    startup.ShowDialog();
}
在启动屏幕窗体中,您应该定义一个计时器,在5秒后关闭窗体:

public partial class StartupBanner : Form
{
    private System.Windows.Forms.Timer _closeTimer = new Timer();

    public StartupBanner(int missingNum, int expiredNum)
    {
        this.InitializeComponent();
        missingLabel.Text = missingNum.ToString() + " MISSING POLICIES";
        expiredLabel.Text = expiredNum.ToString() + " EXPIRED POLICIES";

        this._closeTimer = new System.Windows.Forms.Timer();
        this._closeTimer.Interval = 5000;
        this._closeTimer.Tick += new EventHandler(this._closeTimer_Tick);
        this._closeTimer.Start();
    }

    private void _closeTimer_Tick(object sender, EventArgs e)
    {
        System.Windows.Forms.Timer timer = (System.Windows.Forms.Timer)sender;
        timer.Stop();

        this.Close();
    }
}
编辑:Thread.Sleep()锁定整个线程,例如表单的每个操作,以便它们无法处理任何消息,如单击或按下按钮。它们不会在后台运行,因此最好使用计时器在后台关闭窗体


修复:已删除startup.MdiParent=this

在代码中,MainForm_显示等待“Thread.Sleep(5000)”,所以它变白了,因为主线程睡眠,无法获取任何消息。StartupBanner的形式也有一些原因。我建议您使用线程来避免子函数或子线程拦截主线程,并使MainForm变白。

这是Windows的一项功能,旨在帮助用户处理无响应的程序。当您显示启动屏幕时,Windows会向主窗体发送一条消息,告诉它它不再是活动窗口。这通常会导致它使用非活动窗口的颜色重新绘制窗口标题。该消息还触发Form.Deactivated事件

但这已经不起作用了,您的主线程正忙于执行代码,而不是空闲地“泵送消息循环”。Windows注意到这一点,邮件无法传递。几秒钟后,它会将您的窗口替换为“重影窗口”。它的大小和边框与主窗口相同,但没有内容,只有白色背景。还有一个标题写着“没有反应”。足以让用户知道尝试使用窗口是行不通的


通过使用真正的SplashScreen来避免这种情况,对它的支持是正确的。

在.Net中有内置的对SplashScreen的支持

使用API的最佳方法是

  SplashScreen splash = new SplashScreen("splashscreen.jpg");
  splash.Show(false);
  splash.Close(TimeSpan.FromMilliseconds(2));
  InitializeComponent();

删除第一段代码中的.mdipalent=this,否则会生成异常。除此之外,还有很好的建议!哦,对不起,我没有看到这是一个MDI表单。删除“startup.mdipalent=this;”,因为作为MDI儿童处理启动屏幕没有意义我感到一种难以置信的冲动,想要对一个建议完全无用的启动屏幕的答案进行否决,该屏幕会一直保留到计时器过期为止(尽管我抵制这种冲动)。这不是闪屏的用途。更不用说,自己实现这一点完全是浪费时间,因为对它的支持是在.NET Framework中构建的,比上述方法更加优雅。@Code Gray:我不明白为什么这个示例会如此糟糕?它使用StartupBanner,该代码由他/她自己定义,并且不阻止主窗体的线程。我知道WPF有一个SplashScreen课程。但是WinForms one应该是什么呢?启动屏幕并不意味着“显示5秒钟的无用横幅”。在启动屏幕显示时进行必要的初始化,然后尽快将其从屏幕上取下。这些使用计时器并等待任意定义的时间间隔的建议是毫无意义的。请不要这样做。你似乎没有读过这个问题。用户不希望仅仅创建一个普通的图像屏幕,这仍然是一个问题的答案。您无法使用
SplashScreen
类完成OP想要的操作;它所做的只是显示一个静态图像。