c# - Windows 窗体在闪屏后落后

标签 c# winforms

我正在使用 Windows 表单。我已经设置了一个启动屏幕,以便在打开程序时出现这样的情况。

protected override void OnLoad(EventArgs e)
{
   base.OnLoad(e);
   this.FormBorderStyle = FormBorderStyle.None;
}

private void timer1_Tick(object sender, EventArgs e)
{
   progressBar1.Increment(15);
   if (progressBar1.Value == 30) timer1.Stop();
}

它有一个进度条和一个计时器。我从这里的另一篇文章中得到了这个想法。工作正常,启动画面按预期显示。在之后出现的 Windows 窗体上,我有:

Thread t = new Thread(new ThreadStart(splash));
t.Start();
Thread.Sleep(2000);

InitializeComponent();
t.Abort();

问题如下。当我打开 exe 时,启动屏幕会出现大约 2 秒,当它消失时,下一个表单会出现一秒钟,然后出现在我打开的所有其他窗口后面。

你知道我该如何解决吗?

更新1:

public void splash()
{
   System.Windows.Forms.Application.Run(new Form2());
}

这是我的启动画面

最终更新:

我让它以这种方式工作。

        Splash splash = new Splash();
        Instalador instalador = new Instalador();

        splash.Show();
        Thread.Sleep(2 * 1000);
        splash.Close();

        Application.Run(instalador);

这是主要的。我不知道这有多好,但它确实有效。

最佳答案

要回答您的具体问题,您可能只需在 InitializeComponent 之后添加 this.Activate() 就可以了。

Thread t = new Thread(new ThreadStart(splash));
t.Start();
Thread.Sleep(2000);

InitializeComponent();
this.Activate();
t.Abort();

但是,至少,实现握手可以很好地关闭启动屏幕,而不仅仅是中止线程。

此外,根据您在启动屏幕线程中所做的具体操作,可能存在许多微妙的问题 - 例如您当前遇到的 Z 排序问题。

通常,我会在 Application.Run({main form}) 之前从 Main() 启动启动画面,并调用 Application.Run({splashScreen }) 来自它的线程处理程序。 Application.Run 具有线程关联性,因此启动屏幕将获得自己的 ApplicationContext ,它将正确 Hook Closing/Closed 事件以关闭线程并仅通过调用或 beginInvoking SplashScreen.Close()(通常来自 MainForm_Shown 事件处理程序)。它还具有其他一些小好处,例如包含启动屏幕的 Application.OpenForms

采用这条路线几乎消除了我对闪屏的错误和挫败感。

-开始编辑-

更彻底的示例:

Main()中启动第二个线程和ApplicationContext

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        Thread t = new Thread(new ThreadStart(splash));
        t.IsBackground = true;
        t.SetApartmentState(ApartmentState.STA);
        t.Start();
        Application.Run(new Form1());
    }
    private static void splash()
    {
        Application.Run(new Form2());
    }
}

添加了 SetProgress 方法的启动屏幕,以便您可以根据需要从外部更新它。

public partial class Form2 : Form
{

    public Form2()
    {
        InitializeComponent();
        timer1.Start();
    }
    public void SetProgress()
    {
        if (this.InvokeRequired) //Should have been handled by SplashScreenHandler but check just in case.
            this.BeginInvoke(new Action(SetProgress));
        progressBar1.Increment(15);
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        progressBar1.Increment(15);
        if (progressBar1.Value == 30) timer1.Stop();
    }
}

主窗体:请注意构造函数中没有任何内容,并且 Shown 事件处理程序会关闭启动屏幕,而无需携带引用(如果您打算依赖计时器来实现)状态更新。)

public partial class Form1 : Form
{
    public Form1()
    {
        //Simulate a long init
        Thread.Sleep(2000);

        InitializeComponent();
    }

    private void Form1_Shown(object sender, EventArgs e)
    {
        foreach (var splashScreen in Application.OpenForms.OfType<Form2>())
        {
            splashScreen.BeginInvoke( (Action) delegate () { splashScreen.Close(); });
        }
    }
}

-结束编辑-

关于c# - Windows 窗体在闪屏后落后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42930568/

相关文章:

winforms - 如何在 WinForms 应用程序中关闭 IE WebBrowserControl 上的兼容性 View ?

vb.net - 按名称访问窗体的控件

c# - 跨线程操作无效,即使使用 InvokeRequired

c# - C# WPF 应用程序中的主线程和 UI 线程是否相同?

c# - 创建用于测试目的的 Http 请求

c# - 进程访问的文件,c#,deviare

c# - 如何从文本文件中删除逗号的最后一个索引?

c# - 如何上传文件并查看进度条?

c# - 当我使用 [HttpGet ("public-profile/{avatarName}")] 时如何在 asp.net-core 中 RedirectToAction

c# - 将 Combobox.SelectedItem 转换回 DateTime 会导致 "Specified cast is not valid."