我正在使用 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/