【问题标题】:Windows form going behind after splash screen启动屏幕后 Windows 窗体落后
【发布时间】:2017-03-21 14:52:37
【问题描述】:

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

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

【问题讨论】:

标签: c# winforms


【解决方案1】:

经过长时间的努力,我得到了解决方案。 使用代码进入登录表单 (Form_Load) this.Activate(); 示例:

private void login_Load(object sender, EventArgs e)
{
     this.Activate();
}

【讨论】:

    【解决方案2】:

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

    Thread t = new Thread(new ThreadStart(splash));
    t.Start();
    Thread.Sleep(2000);
    
    InitializeComponent();
    this.Activate();
    t.Abort();
    

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

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

    通常,我从 Main() before Application.Run({main form}) 启动启动画面,并从它的线程处理程序调用 Application.Run({splashScreen})。 Application.Run 具有线程关联性,因此初始屏幕将获得自己的ApplicationContext,这将正确挂钩 Closing/Closed 事件以关闭线程并仅通过调用或 beginInvoking SplashScreen.Close() 引发 ThreadExit(通常来自 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(); });
            }
        }
    }
    

    -结束编辑-

    【讨论】:

    • Activate 没有修复它。我会看看你说的另一件事
    【解决方案3】:

    我遇到了同样的问题,在纠结了很长时间后,我最终在关闭初始屏幕后在主窗体的 Load 事件中执行了以下操作:

    //Manually activate frmMain as it gets back in the Z-order by Windows when splash screen closes.
    NativeMethods.SetForegroundWindow(this.Handle);
    this.Activate();
    

    其中“SetForegroundWindow”定义如下:

    /// <summary>
    /// Sets foreground window
    /// </summary>
    /// <param name="hWnd"></param>
    /// <returns></returns>
    [DllImport("user32.dll")]
    internal static extern bool SetForegroundWindow(IntPtr hWnd);
    

    话虽如此,我们可能需要查看更多您的代码。

    【讨论】:

    • 无法让它工作。我在哪里定义“SetForegroundWindow”?
    猜你喜欢
    • 1970-01-01
    • 2014-09-19
    • 2010-09-21
    • 1970-01-01
    • 2011-03-10
    • 2017-10-29
    • 2019-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多