一旦Splash Screen关闭,表单将在后台打开

时间:2017-01-12 06:20:38

标签: c# forms winforms timer splash-screen

我创建了一个启动画面。在我的启动画面上,我给出了一个进度条和两个按钮来执行某些操作。单击按钮时,一旦这些表单的模块完全加载并显示进度条上的进度,我将显示相应的表单。一旦相应的表格打开,Splash屏幕将关闭,表格应显示在屏幕顶部。

但问题是,在关闭启动画面后,我的表单在后台打开,或者你可以说失焦不应该发生。我已经检查了谷歌或stackoverflow上给出的各种解决方案,但无法解决我的问题。

enter image description here

以下是我的代码:
SplashScreen.cs

// <--- Data Members

// --->

public SplashScreen()
{
    InitializeComponent();
    this.Opacity = 0.0;
    UpdateTimer.Interval = TIMER_INTERVAL;
    UpdateTimer.Start();
    this.ClientSize = this.BackgroundImage.Size;
}

static public void ShowSplashScreen()
{
    if (ms_frmSplash != null)
    {
        return;
    }

    ms_oThread = new Thread(new ThreadStart(SplashScreen.ShowForm));
    ms_oThread.IsBackground = true;
    ms_oThread.SetApartmentState(ApartmentState.STA);
    ms_oThread.Start();

    while (ms_frmSplash == null || ms_frmSplash.IsHandleCreated == false)
    {
        System.Threading.Thread.Sleep(TIMER_INTERVAL);
    }
}

static public void CloseForm()
{
    if (ms_frmSplash != null && ms_frmSplash.IsDisposed == false)
    {
        ms_frmSplash.m_dblOpacityIncrement = -ms_frmSplash.m_dblOpacityDecrement;
    }

    ms_oThread = null;
    ms_frmSplash = null;
}

static public void SetStatus(string newStatus)
{
    SetStatus(newStatus, true);
}

static public void SetStatus(string newStatus, bool setReference)
{
    if (ms_frmSplash == null)
    {
        return;
    }

    ms_frmSplash.m_sStatus = newStatus;

    if (setReference)
    {
        ms_frmSplash.SetReferenceInternal();
    }
}

static public void SetReferencePoint()
{
    if (ms_frmSplash == null)
    {
        return;
    }
    ms_frmSplash.SetReferenceInternal();

}

static private void ShowForm()
{
    ms_frmSplash = new SplashScreen();
    Application.Run(ms_frmSplash);
}

private void SetReferenceInternal()
{
    if (m_bDTSet == false)
    {
        m_bDTSet = true;
        m_dtStart = DateTime.Now;
        ReadIncrements();
    }
    double dblMilliseconds = ElapsedMilliSeconds();
    m_alActualTimes.Add(dblMilliseconds);
    m_dblLastCompletionFraction = m_dblCompletionFraction;
    if (m_alPreviousCompletionFraction != null && m_iIndex < m_alPreviousCompletionFraction.Count)
    {
        m_dblCompletionFraction = (double)m_alPreviousCompletionFraction[m_iIndex++];
    }
    else
    {
        m_dblCompletionFraction = (m_iIndex > 0) ? 1 : 0;
    }
}

private double ElapsedMilliSeconds()
{
    TimeSpan ts = DateTime.Now - m_dtStart;
    return ts.TotalMilliseconds;
}

private void ReadIncrements()
{
    string sPBIncrementPerTimerInterval = SplashScreenXMLStorage.Interval;
    double dblResult;

    if (Double.TryParse(sPBIncrementPerTimerInterval, System.Globalization.NumberStyles.Float, System.Globalization.NumberFormatInfo.InvariantInfo, out dblResult) == true)
    {
        m_dblPBIncrementPerTimerInterval = dblResult;
    }
    else
    {
        m_dblPBIncrementPerTimerInterval = .0015;
    }

    string sPBPreviousPctComplete = SplashScreenXMLStorage.Percents;

    if (sPBPreviousPctComplete != "")
    {
        string[] aTimes = sPBPreviousPctComplete.Split(null);
        m_alPreviousCompletionFraction = new ArrayList();

        for (int i = 0; i < aTimes.Length; i++)
        {
            double dblVal;
            if (Double.TryParse(aTimes[i], System.Globalization.NumberStyles.Float, System.Globalization.NumberFormatInfo.InvariantInfo, out dblVal) == true)
            {
                m_alPreviousCompletionFraction.Add(dblVal);
            }
            else
            {
                m_alPreviousCompletionFraction.Add(1.0);
            }
        }
    }
    else
    {
        m_bFirstLaunch = true;
        m_sTimeRemaining = "";
    }
}

private void StoreIncrements()
{
    string sPercent = "";
    double dblElapsedMilliseconds = ElapsedMilliSeconds();
    for (int i = 0; i < m_alActualTimes.Count; i++)
    {
        sPercent += ((double)m_alActualTimes[i] / dblElapsedMilliseconds).ToString("0.####", System.Globalization.NumberFormatInfo.InvariantInfo) + " ";
    }

    SplashScreenXMLStorage.Percents = sPercent;
    m_dblPBIncrementPerTimerInterval = 1.0 / (double)m_iActualTicks;
    SplashScreenXMLStorage.Interval = m_dblPBIncrementPerTimerInterval.ToString("#.000000", System.Globalization.NumberFormatInfo.InvariantInfo);
}

public static SplashScreen GetSplashScreen()
{
    return ms_frmSplash;
}

private void UpdateTimer_Tick(object sender, System.EventArgs e)
{
    if (Program.isRadarSelected)
    {
        if (count >= 100)
        {
            UpdateTimer.Stop();
            this.Close();
        }
        else
        {
            updateProgressBar();
            count += 5;
        }
    }

    if (m_dblOpacityIncrement > 0)
    {
        m_iActualTicks++;
        if (this.Opacity < 1)
        {
            this.Opacity += m_dblOpacityIncrement;
        }
    }
    else
    {
        if (this.Opacity > 0)
        {
            this.Opacity += m_dblOpacityIncrement;
        }
        else
        {
            StoreIncrements();
            UpdateTimer.Stop();
            this.Close();
        }
    }
}

private void updateProgressBar()
{

   SplashScreen.SetStatus("Loading : " + count + " %");

   statusLabel.Text = m_sStatus;
   m_dblLastCompletionFraction += m_dblPBIncrementPerTimerInterval;

   int width = (int)Math.Floor(statusPanel.ClientRectangle.Width * m_dblLastCompletionFraction);
   int height = statusPanel.ClientRectangle.Height;
   int x = statusPanel.ClientRectangle.X;
   int y = statusPanel.ClientRectangle.Y;

   if (width > 0 && height > 0)
   {
       m_rProgress = new Rectangle(x, y, width, height);
       if (!statusPanel.IsDisposed)
       {
            Graphics g = statusPanel.CreateGraphics();
            LinearGradientBrush brBackground = new LinearGradientBrush(m_rProgress, Color.FromArgb(58, 96, 151), Color.FromArgb(181, 237, 254), LinearGradientMode.Horizontal);
            g.FillRectangle(brBackground, m_rProgress);
            g.Dispose();
        }
    }
}

private void RadarSelectionButton_Click(object sender, EventArgs e)
{
    Program.isButtonClicked= true;
}

Program.cs的

internal static class Program
{
    public static bool isButtonClicked= false;

    [STAThread]
    private static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        SplashScreen.ShowSplashScreen();
        Application.DoEvents();

        while (!isButtonClicked)
        {
            System.Threading.Thread.Sleep(50);
        }

        Application.Run(new MyForm());
        SplashScreen.CloseForm();
    }
}

1 个答案:

答案 0 :(得分:1)

据我所知,Application.Run(...)正在阻止,这意味着在主窗口关闭之前,您的启动画面永远不会关闭。您可以尝试下面的代码。让我知道它是怎么回事。

internal static class Program
{
    public static bool isButtonClicked= false;

    [STAThread]
    private static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        SplashScreen.ShowSplashScreen();
        Application.DoEvents();

        while (!isButtonClicked)
        {
            System.Threading.Thread.Sleep(50);
        }

        var window = new MyForm();
        window.Load += (s, e) => 
        {        
             SplashScreen.CloseForm();
             window.Activate();
        }
        Application.Run(window);

    }
}

关于您CloseForm方法,我不确定您打算如何工作。你唯一要做的就是设置不透明度?但就你写的而言,这不是你的问题。但我认为你需要在Application.Run(..)退出之前发出启动画面的主窗口信号。 还有ShowSplashScreen方法中的while循环;为什么?考虑使用ManualResetEvent之类的东西来等待线程之间的信号。总是更好地等待事件而不是轮询。