我创建了一个启动画面。在我的启动画面上,我给出了一个进度条和两个按钮来执行某些操作。单击按钮时,一旦这些表单的模块完全加载并显示进度条上的进度,我将显示相应的表单。一旦相应的表格打开,Splash屏幕将关闭,表格应显示在屏幕顶部。
但问题是,在关闭启动画面后,我的表单在后台打开,或者你可以说失焦不应该发生。我已经检查了谷歌或stackoverflow上给出的各种解决方案,但无法解决我的问题。
以下是我的代码:
的 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();
}
}
答案 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
之类的东西来等待线程之间的信号。总是更好地等待事件而不是轮询。