Windows Forms启动画面 - 在加载主窗体时显示一个窗体

6
我正在尝试让启动画面先出现,然后在启动画面之后显示MainForm。但是我在启动画面中放置的进度条无法到达进度条的末端,并且程序继续运行而不起作用。
如何在加载主窗体时显示启动画面?
我的代码类似于以下内容:
public partial class SplashForm : Form
{
    public SplashForm()
    { 
        InitializeComponent();
    }
    private void SplashForm_Load(object sender, EventArgs e)
    {
        timer1.Enabled = true;
        timer1.Start();
        timer1.Interval = 1000;
        progressBar1.Maximum = 10;
        timer1.Tick += new EventHandler(timer1_Tick);
    }
    public void timer1_Tick(object sender, EventArgs e)
    {
        if (progressBar1.Value != 10)
        {
            progressBar1.Value++;
        }
        else
        {
            timer1.Stop();
            Application.Exit();
        }
    }     
}

以下是MainForm代码的第一部分:
public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        Application.Run(new SplashForm());
    }
}

你能展示一下创建这个表单的代码吗?pbcarrega是在哪里初始化的? - Paul Sasik
pbcarrega是ProgressBar的名称。 - Leandro Mont
这段代码是闪屏窗体的代码,但您想了解主窗体的代码吗? - Leandro Mont
@Novatec - 您需要提供足够的代码来让我们重新创建您的问题。仅仅挑选一些您认为相关的代码行是不够的。请发布最小,完整和可验证的 代码以复制您的问题。 - Enigmativity
我现在发布了Form Main的部分,我看了一下,我觉得在Application.Run()的那部分做错了什么。 - Leandro Mont
现在,当我更改了代码后,进度条达到了100,但是我不知道如何在启动画面之后显示主窗体。 - Leandro Mont
2个回答

25

创建闪屏界面的方法有多种:

  • 可以依赖于 WindowsFormsApplicationBase 的闪屏功能。

  • 也可以通过在另一个 UI 线程上显示一个窗体,并在主窗体成功加载后隐藏该窗体来实现该功能。

在本文中,我将展示这两种解决方案的示例。

注意:如果您正在寻找在数据加载过程中显示加载窗口或加载 gif 动画的方法,请查看此文章:Show Loading animation during loading data in other thread

选项1 - 使用 WindowsFormsApplicationBase 闪屏功能

  1. Microsoft.VisualBasic.dll 添加到您的项目引用中。
  2. 创建一个 MyApplication 类,从 WindowsFormsApplicationBase 派生。
  3. 覆盖 OnCreateMainForm 方法,并将您想要作为启动窗体的窗体分配给 MainForm 属性。
  4. 覆盖 OnCreateSplashScreen 方法,并将您想要显示为闪屏界面的窗体分配给 SplashScreen 属性。

  5. 在您的 Main 方法中,创建一个 MyApplication 的实例,并调用其 Run 方法。

示例

using System;
using System.Windows.Forms;
using Microsoft.VisualBasic.ApplicationServices;

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(true);
        var app = new MyApplication();
        app.Run(Environment.GetCommandLineArgs());
    }
}
public class MyApplication : WindowsFormsApplicationBase
{
    protected override void OnCreateMainForm()
    {
        MainForm = new YourMainForm();
    }
    protected override void OnCreateSplashScreen()
    {
        SplashScreen = new YourSplashForm();
    }
}

选项2-使用不同的UI线程实现该功能

您可以通过在不同的UI线程中显示闪屏来自己实现该功能。为此,您可以订阅 Program 类中主窗体的 Load 事件,在那里显示和关闭您的闪屏。

示例

using System;
using System.Threading;
using System.Windows.Forms;

static class Program
{
    static Form SplashScreen;
    static Form MainForm;
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        //Show Splash Form
        SplashScreen = new Form();
        var splashThread = new Thread(new ThreadStart(
            () => Application.Run(SplashScreen)));
        splashThread.SetApartmentState(ApartmentState.STA);
        splashThread.Start();

        //Create and Show Main Form
        MainForm = new Form8();
        MainForm.Load += MainForm_LoadCompleted;
        Application.Run(MainForm);
    }
    private static void MainForm_LoadCompleted(object sender, EventArgs e)
    {
        if (SplashScreen != null && !SplashScreen.Disposing && !SplashScreen.IsDisposed)
            SplashScreen.Invoke(new Action(() => SplashScreen.Close()));
        MainForm.TopMost = true;
        MainForm.Activate();
        MainForm.TopMost = false;
    }
}
注意:要展示一个平滑边缘的自定义形状启动画面,请查看此帖子:Windows Forms Transparent Background Image

1
我把名称改得更加友好。现在,要使用此代码与您的表单名称一起使用,只需查找并替换所有SplashForm为您想要的启动窗体名称(FormSplash),并查找并替换所有MainForm为您想要的主窗体名称(Form1)。 - Reza Aghaei
1
我可以使用相同的代码更改一些部分以在ProgressBar中使用吗?因为我现在不会使用Thread.Sleep。 - Leandro Mont
1
@Novatec 你可以更改代码的任何部分并随意使用它,但我不建议在启动屏幕中使用进度条,而是应该在启动屏幕上显示一个加载图像(一个动画 .gif)。我认为这是启动屏幕的一个很好的实现,对其他用户也会有帮助 :) - Reza Aghaei
1
我尝试了这个示例,它可以工作,但是当我的启动屏幕关闭时,我的窗体会进入后台。有什么建议可以解决这个问题吗? - Rawat
1
@Rawat 我无法重现这个问题,但是作为建议,在 MainForm_LoadCompleted 事件处理程序中,您可以使用 myMainForm.TopMost = true; myMainForm.Activate(); myMainForm.TopMost = false; 替代 myMainForm.Activate(); - Reza Aghaei
显示剩余8条评论

0

我在我的Winforms应用程序中已经有了一个启动画面好几年了。这个启动画面会停留5秒钟,是非模态、但最顶层的。初始化过程一直都没有问题。

在主程序中,我什么都没改。

    [STAThread]
    static void Main()
    {
        Application.SetHighDpiMode(HighDpiMode.SystemAware);
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new FrmMain());
    }

    //---------------------------------------------------------------------

这是我的启动画面,它有一个计时器,在5秒后自动关闭

    public partial class FrmSplash : Form
    {
      private Timer _timer;
      private int _cTick = 5;

      public FrmSplash()
      {
        InitializeComponent();
        _timer = new Timer() { Interval = 1000, Enabled = true };
        _timer.Tick += CTick;
      }

      private void CTick(object sender, EventArgs e)
      {
        if (--_cTick<0)
        {
            _timer.Enabled = false;
            Close();

        }
      }
   }

在主窗体构造函数中,我调用了启动画面,然后跟着使用 Application.DoEvents() 方法,这样它就会显示在屏幕上,同时我的初始化也可以继续进行。
   //---------------------------------------------------------------------

   public FrmMain()
   {
      InitializeComponent();
      var  FrmSplash = new FrmSplash();
      FrmSplash.Show();
      Application.DoEvents();
   }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接