Windows窗体在启动画面后落后

时间:2017-03-21 14:52:37

标签: c# winforms

我正在使用Windows表单。我在打开这样的程序时设置了一个启动画面。

class SharePrice
{
private:
    double shareVal;
public:
    SharePrice();
    SharePrice(double price);
    double getPrice() const { return shareVal; }
    void setPrice(double price);
};

SharePrice::SharePrice()
{
    setPrice(0);
}

SharePrice::SharePrice(double price)
{
    setPrice(price);
}

void SharePrice::setPrice(double price)
{
    if (price > 0)
        shareVal = price;
    else
        shareVal = 0;
}

它有一个进度条和一个计时器。我从另一篇文章中得到了这个想法。这工作正常,启动画面正好应该出现。在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();
}

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

你知道我该怎么办呢?

更新1:

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

InitializeComponent();
t.Abort();

这是我的启动画面

最终更新:

我让它以这种方式工作。

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

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

3 个答案:

答案 0 :(得分:3)

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

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

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

然而,至少,实施握手可以很好地关闭启动画面,而不仅仅是中止线程。

此外,根据您在启动画面线程中的具体操作,可能存在大量细微问题 - 例如您目前正在进行的Z排序问题。

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

采用这种方式几乎消除了我对启动画面的错误和挫折。

- 开始编辑 -

更全面的例子:

Application.OpenForms

中启动第二个主题和ApplicationContext
Main()

添加了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

- 结束编辑 -

答案 1 :(得分:0)

我遇到了同样的问题,经过很长一段时间后,我在关闭启动画面后,在主窗体的Load事件中完成了以下操作:

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

其中&#34; SetForegroundWindow&#34;定义如下:

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

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

答案 2 :(得分:0)

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

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