最小自包含WPF/C#用于生成启动画面,显示x秒

问题描述:

我在想,为什么我的启动画面在下面的代码中x秒后不消失?在C#中,我启动一个线程,等待x秒,然后尝试将close()发送到启动窗口,同时将其显示在屏幕上。最小自包含WPF/C#用于生成启动画面,显示x秒

// FILE: splashy.cs 
using System; 
using System.IO; 
using System.Xml; 
using System.Text; 
using System.Windows; 
using System.Windows.Markup; 
using System.Threading; 

namespace Splashy 
{ 
    class MySplash 
    { 
     Window win; 

     public void Show() 
     { 
      var mem  = new MemoryStream(
          ASCIIEncoding.UTF8.GetBytes(xmlstr)); 

      win   = (Window)XamlReader.Load(mem); 
      (new Thread(CloseIt)).Start(); 
      win.Show(); 
     } 

     public void CloseIt() { 
      Thread.Sleep(4*1000); 
      //MessageBox.Show("CLOSE"); 
      win.Dispatcher.Invoke(() => win.Close()); 
     } 

     static string xmlstr = @" 
<Window 
    xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' 
    xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' 
    Name='WindowSplash' 
    Title='My Splash Window...' 
    WindowStyle='None' 
    WindowStartupLocation='CenterScreen' 
    Background='White' 
    ShowInTaskbar ='true' 
    Width='350' Height='130' 
    ResizeMode = 'NoResize' > 

<Window.Resources> 
    <Style TargetType='{x:Type Label}'> 
      <Setter Property='FontFamily' Value='Consolas'/> 
      <Setter Property='Background' Value='Blue'/> 
      <Setter Property='Foreground' Value='AntiqueWhite'/> 
    </Style> 
</Window.Resources> 

<Grid> 

<Grid.RowDefinitions> 
    <RowDefinition Height='Auto'/> 
    <RowDefinition Height='*'/> 
    <RowDefinition Height='Auto'/> 
</Grid.RowDefinitions> 

<Grid.ColumnDefinitions> 
    <ColumnDefinition Width='Auto'/> 
    <ColumnDefinition Width='*'/> 
</Grid.ColumnDefinitions> 

<Label 
    Grid.ColumnSpan='2' 
    Grid.Row='0' 
    Content='MyApplication 1.0' 
    FontWeight='Bold' 
    FontFamily='Consolas' 
    Background='AntiqueWhite' 
    Foreground='Black'/> 

<Label 
    Grid.ColumnSpan='2' 
    Grid.Row='2' 
    Content='' 
    FontWeight='Bold' 
    FontFamily='Consolas' 
    Background='AntiqueWhite' 
    Foreground='Black'/> 


<Label 
    Grid.Column='0' 
    Grid.Row='1' 
    FontFamily='Webdings' Content='&#xc2;' FontSize='80' /> 

<StackPanel 
    Grid.Row='1' 
    Grid.Column='1' 
    Background='Blue' 
    > 
    <Label Content='Programmer: John Smith'/> 
    <Label Content='Email:  [email protected]'/> 
    <Label Content='Dates:  2017'/> 
</StackPanel> 

</Grid> 

</Window> 
"; 

    } //end-class 

    class MyApp 
    { 
     [STAThread] 
     static void Main(string[] args) 
     { 
      (new MySplash()).Show(); 
     } 
    } //end-class 
} //end-namespace 

这里是什么我CSC.EXE命令行查找从系统上方的C#代码编译(...)控制台模式下的C++里面的应用为例:

C:\WINDOWS\Microsoft.Net\Framework64\v4.0.30319\csc.exe 
/out:splashy.exe 
/nologo 
/target:winexe 
splashy.cs 
/reference:"C:\WINDOWS\Microsoft.Net\Framework64\v4.0.30319\WPF\presentationframework.dll" 
/reference:"C:\WINDOWS\Microsoft.Net\Framework64\v4.0.30319\WPF\windowsbase.dll" 
/reference:"C:\WINDOWS\Microsoft.Net\Framework64\v4.0.30319\WPF\presentationcore.dll" 
/reference:"C:\WINDOWS\Microsoft.Net\Framework64\v4.0.30319\System.Xaml.dll" 

程序的确没什么泵送消息队列并将窗口消息分派给窗口。因此,您关闭窗口的操作将无效,该窗口将发送WM_CLOSE消息到窗口。

解决这个在您的例子是使用win.ShowDialog()而不是win.Show()最简单的方法。 ShowDialog()方法取代任何消息泵循环已经运行,用它自己的替代它(这样做是为了拦截在模态对话框启动时不应该分派给其他窗口的用户输入消息)。但它并不要求已经有消息泵循环,它所运行的循环就足以接收你的WM_CLOSE并关闭窗口。

如果您想更正确地做到这一点,可以将Application对象添加到您的示例中,并调用Application.Run()来提供消息泵循环。如果您在某些时候希望显示多个窗口或需要非模态UI,则可能需要执行此操作。

+0

谢谢!重写并添加“Application.Run(win)”后,它可以正常工作。 –

+0

@Bill:看着你的问题,看起来你从未接受任何提供给你的答案。您可能想阅读[当某人回答我的问题时该怎么办?](https://stackoverflow.com/help/someone-answers):) –

这些是为我工作了修改:

// FILE: splashy.cs 
using System; 
using System.IO; 
using System.Xml; 
using System.Text; 
using System.Windows; 
using System.Windows.Markup; 
using System.Threading; 

namespace Splashy 
{ 
    class MySplash 
    { 
     Window win; 

     public Window CreateWindow() 
     { 
      var mem  = new MemoryStream(
           ASCIIEncoding.UTF8.GetBytes(xmlstr)); 
      win   = (Window)XamlReader.Load(mem); 
      (new Thread(CloseIt)).Start(); 
      return win; 
     } 

     public void CloseIt() { 
      Thread.Sleep(2000); 
      Application.Current.Dispatcher.Invoke(() => { 
       win.Close(); 
      }); 
     } 

     [STAThread] 
     static void Main(string[] args) 
     { 
      Application app = new Application(); 
      MySplash splash = new MySplash(); 
      Window  win = splash.CreateWindow(); 
      app.Run(win); 
     } 

     static string xmlstr = @" 
      <Windows ...> 
      <!-- ... Omitted to save space ... --> 
      <Window/> 
     "; 

    } //end-class 
} //end-namespace