2017-09-21 5 views
2

Je me demande pourquoi mon écran de démarrage ne disparaît pas après x secondes dans le code ci-dessous? En C#, je lance un thread, qui attend x secondes, puis essaie d'envoyer un close() à la fenêtre de démarrage alors qu'il est affiché sur l'écran.WPF/C# autonome minimal pour générer un écran de démarrage qui affiche pendant x secondes

// 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 

Voici un exemple de ce que ma ligne de commande csc.exe cherche la compilation ci-dessus du code C# de système (...) à l'intérieur du mode console C++ application:

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" 

Répondre

1

Votre programme ne fait rien pour pomper la file d'attente des messages et envoyer les messages de la fenêtre aux fenêtres. Donc, votre tentative de fermer la fenêtre, qui envoie un message WM_CLOSE à la fenêtre, n'a aucun effet. La façon la plus simple de résoudre ceci dans votre exemple serait d'utiliser win.ShowDialog() au lieu de win.Show(). La méthode ShowDialog() remplace la boucle de pompe à messages déjà exécutée, en la remplaçant par la sienne (elle le fait pour intercepter les messages d'entrée d'utilisateur qui ne doivent pas être envoyés à d'autres fenêtres pendant que la boîte de dialogue modale est activée). Mais il ne nécessite pas qu'il y ait déjà une boucle de message-pompe, et celle qu'il exécute suffira pour recevoir votre WM_CLOSE et fermer la fenêtre.

Si vous voulez le faire plus correctement, vous pouvez ajouter un objet Application à votre échantillon et appeler le Application.Run() pour fournir la boucle de pompe de message. Vous voudrez peut-être faire cela si vous pensez avoir besoin d'afficher plusieurs fenêtres ou si vous avez besoin d'une interface utilisateur non modale.

+0

Merci! Après avoir réécrit et ajouté "Application.Run (win)" cela fonctionne. –

+0

@Bill: en regardant vos questions, il semble que vous n'avez jamais accepté de réponse. Vous pourriez vouloir lire [Que dois-je faire quand quelqu'un répond à ma question?] (Https://stackoverflow.com/help/someone-answers) :) –

0

Ce sont les modifications qui ont travaillé pour moi:

// 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