Frage

Ich möchte einen Begrüßungsbildschirm anzeigen, während die Anwendung geladen wird.Ich habe ein Formular mit ein system-tray-Steuerung verbunden.Ich möchten, dass der Begrüßungsbildschirm angezeigt, während das Formular geladen, das dauert ein wenig, da es den Zugriff auf einen web-service-API zu füllen einige Dropdown-Menüs.Ich will auch tun einige grundlegende Tests für Abhängigkeiten vor dem laden (, dass ist, die web-service verfügbar ist, wird die Konfiguration Datei ist lesbar).Wie jede phase des Start geht, will ich ein update der splash-screen mit dem Fortschritt.

Ich lese viel auf dem Durchzug, aber ich bin verloren, wo sich dieses gesteuert werden soll, aus (die main() Methode?).Ich bin auch fehlen, wie Application.Run() funktioniert, ist dies, wo die Fäden für diese soll erstellt werden?Nun, wenn das Formular mit dem system-tray-Steuerung ist das "Leben" bilden, sollten die splash von dort kommen?Wäre es nicht nicht laden, bis die form fertig ist eh?

Ich bin nicht auf der Suche nach einer code-handout, eher ein Algorithmus/Methode, so kann ich dies herauszufinden und ein für alle mal :)

War es hilfreich?

Lösung

Nun, für eine ClickOnce-Anwendung, die ich bereitgestellt, die in der Vergangenheit verwendeten wir den Microsoft.VisualBasic namespace Griff die splash-screen-threading.Sie verweisen können, und verwenden Sie das Microsoft.VisualBasic Montage von C# in .NET 2.0 und es gibt eine Menge netter Service.

  1. Die wichtigste form von Erben Microsoft.VisualBasic.WindowsFormsApplicationBase
  2. Überschreiben Sie die "OnCreateSplashScreen" - Methode wie folgt:

    protected override void OnCreateSplashScreen()
    {
        this.SplashScreen = new SplashForm();
        this.SplashScreen.TopMost = true;
    }
    

Sehr einfach, es zeigt Ihre SplashForm (die Sie erstellen müssen) beim laden Los ist, dann schließt es sich automatisch, wenn das Hauptformular geladen wurde.

Das macht die Sache einfacher, und die VisualBasic.WindowsFormsApplicationBase ist natürlich auch von Microsoft getestet und hat eine Menge an Funktionalität, die Ihr Leben viel einfacher in Winforms, sogar in einer Anwendung, die zu 100% C#.

Am Ende des Tages, es ist alles, IL bytecode sowieso, also warum es nicht verwenden?

Andere Tipps

Der trick ist, zu erstellen separaten thread verantwortlich für splash-screen zeigt.
Wenn Sie Sie laufen app .net erstellt Haupt-thread und lädt genannten (Haupt -) form.Zu verbergen, die harte Arbeit, die Sie verstecken können Hauptformular, bis das laden fertig ist.

Unter der Annahme, dass Form1 - ist die wichtigste form und SplashForm ist top-Niveau, borderles schön Spritzen form:

private void Form1_Load(object sender, EventArgs e)
{
    Hide();
    bool done = false;
    ThreadPool.QueueUserWorkItem((x) =>
    {
        using (var splashForm = new SplashForm())
        {
            splashForm.Show();
            while (!done)
                Application.DoEvents();
            splashForm.Close();
        }
    });

    Thread.Sleep(3000); // Emulate hardwork
    done = true;
    Show();
}

Nach Suche über Google und SO für Lösungen, das ist mein Favorit:http://bytes.com/topic/c-sharp/answers/277446-winform-startup-splash-screen

FormSplash.cs:

public partial class FormSplash : Form
{
    private static Thread _splashThread;
    private static FormSplash _splashForm;

    public FormSplash() {
        InitializeComponent();
    }

    /// <summary>
    /// Show the Splash Screen (Loading...)
    /// </summary>
    public static void ShowSplash()
    {
        if (_splashThread == null)
        {
            // show the form in a new thread
            _splashThread = new Thread(new ThreadStart(DoShowSplash));
            _splashThread.IsBackground = true;
            _splashThread.Start();
        }
    }

    // called by the thread
    private static void DoShowSplash()
    {
        if (_splashForm == null)
            _splashForm = new FormSplash();

        // create a new message pump on this thread (started from ShowSplash)
        Application.Run(_splashForm);
    }

    /// <summary>
    /// Close the splash (Loading...) screen
    /// </summary>
    public static void CloseSplash()
    {
        // need to call on the thread that launched this splash
        if (_splashForm.InvokeRequired)
            _splashForm.Invoke(new MethodInvoker(CloseSplash));

        else
            Application.ExitThread();
    }
}

Programm.cs:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
        // splash screen, which is terminated in FormMain
        FormSplash.ShowSplash();

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        // this is probably where your heavy lifting is:
        Application.Run(new FormMain());
    }
}

FormMain.cs

    ...

    public FormMain()
    {
        InitializeComponent();            

        // bunch of database access, form loading, etc
        // this is where you could do the heavy lifting of "loading" the app
        PullDataFromDatabase();
        DoLoadingWork();            

        // ready to go, now close the splash
        FormSplash.CloseSplash();
    }

Ich hatte Probleme mit dem Microsoft.VisualBasic Lösung-Gearbeitet, finden Sie auf XP, aber unter Windows 2003 Terminal Server, das Hauptformular der Anwendung angezeigt (nachdem die splash-screen) im hintergrund und die Taskleiste würde blinken.Und bringen ein Fenster in den Vordergrund/Mittelpunkt in code ist eine ganz andere Dose Würmer, die Sie können Google/SO für.

Dies ist eine alte Frage, aber ich flog über Sie hinweg, wenn Sie versuchen zu finden, ein threaded-splash-Bildschirm-Lösung für WPF umfassen könnten-animation.

Hier ist, was ich letztendlich zusammengetragen:

App.XAML:

<Application Startup="ApplicationStart" …

App.XAML.cs:

void ApplicationStart(object sender, StartupEventArgs e)
{
        var thread = new Thread(() =>
        {
            Dispatcher.CurrentDispatcher.BeginInvoke ((Action)(() => new MySplashForm().Show()));
            Dispatcher.Run();
        });
        thread.SetApartmentState(ApartmentState.STA);
        thread.IsBackground = true;
        thread.Start();

        // call synchronous configuration process
        // and declare/get reference to "main form"

        thread.Abort();

        mainForm.Show();
        mainForm.Activate();
  }

Ich empfehle aufrufen Activate(); direkt nach dem letzten Show(); in der Antwort des aku.

Zitieren von MSDN:

Aktivieren eines Formulars, bringt es auf den vor, wenn dieser das aktive Anwendung, oder es blinkt das Fenster überschrift, wenn diese nicht die aktive Anwendung.Das Formular muss gut sichtbar sein für diese Methode keine Auswirkung.

Wenn Sie nicht aktivieren Sie Ihre wichtigsten form, kann es angezeigt werden hinter alle anderen geöffneten Fenster, so dass es sich ein bisschen albern.

Ich denke, mit einer Methode wie aku ' s oder Guy ist der Weg zu gehen, aber ein paar Dinge zu nehmen, die konkrete Beispiele:

  1. Die Grundvoraussetzung wäre, um zu zeigen Ihre Spritzen auf einem separaten thread so bald wie möglich.Das ist die Art, wie ich möchte lean, ähnlich wie die aku ' s illustrated, da es die Weise, die ich bin am meisten vertraut mit.Ich war nicht bewusst von der VB-Funktion Kerl erwähnt.Und dachte sogar es ist ein VB Bibliothek, hat er Recht-es ist alles, IL am Ende.Also, auch wenn es sich anfühlt, dirty es ist gar nicht so schlecht!:) Ich denke, Sie wollen sicher sein, dass entweder die VB stellt einen separaten thread für das überschreiben oder dass Sie selbst eines erstellen -- definitiv Forschung.

  2. Angenommen, Sie erstellen einen anderen thread, um dieses splash, werden Sie wollen, vorsichtig zu sein, der cross-thread-UI updates.Ich erwähne dies, weil Sie erwähnt die Aktualisierung Fortschritt.Im Grunde, um sicher zu sein, müssen Sie zu nennen, eine update-Funktion (die Sie erstellen) auf das splash-Formular mit einem Delegierten.Geben Sie Delegierte zu den Invoke Funktion auf Ihrer splash-Bildschirm ist das form-Objekt.In der Tat, wenn Sie rufen Sie das splash-Formular direkt an update progress/UI-Elemente, erhalten Sie eine Ausnahme, vorausgesetzt, Sie sind läuft auf die .Net CLR 2.0.Als Faustregel gilt, dass jedes UI-element in einem Formular aktualisiert werden muss, indem der thread, der es erstellt-das ist, was Form.Invoke versichert.

Schließlich, ich würde wahrscheinlich entscheiden, erstellen Sie die splash (wenn nicht mit der VB overload) in der main-Methode Ihres Codes.Für mich ist das besser, als die wichtigste form zur Erstellung des Objekts und so fest gebunden.Wenn Sie diesem Ansatz, ich würde vorschlagen, erstellen Sie eine einfache Schnittstelle, die splash-screen implementiert-etwas wie IStartupProgressListener -- empfängt start-up-Fortschritt-updates über eine member-Funktion.Dies wird Ihnen ermöglichen, leicht swap in/out-Klasse wie nötig, und gut entkoppelt Sie den code.Das splash Formular kann auch wissen, Wann zu schließen, selbst wenn Sie zu Benachrichtigen, wenn start-up ist komplett.

Eine einfache Möglichkeit ist die Verwendung so etwas wie main():

<STAThread()> Public Shared Sub Main()

    splash = New frmSplash
    splash.Show()

    ' Your startup code goes here...

    UpdateSplashAndLogMessage("Startup part 1 done...")

    ' ... and more as needed...

    splash.Hide()
    Application.Run(myMainForm)
End Sub

Wenn die .NET CLR Ihre Applikation startet, erstellt es eine "main" - thread und beginnt mit der Ausführung Ihrer main () - auf diesem thread.Die Anwendung.Run(myMainForm) am Ende der zwei Dinge tut:

  1. Startet die Windows message pump', mit dem thread, der wurde Ausführung von main() als GUI-thread.
  2. Bezeichnet Ihr "main-form" als "shutdown" form " für die Anwendung.Wenn der Benutzer schließt, die form, dann die Anwendung.Run() beendet und die Steuerung kehrt zu Ihrer main () -, wo können Sie Herunterfahren Sie möchten.

Es gibt keine Notwendigkeit, um zu laichen einen thread zu kümmern sich um die splash-Fenster, und in der Tat ist dies eine schlechte Idee, denn dann würden Sie haben zu verwenden-thread-sicheren Techniken, um die update-splash-Inhalt von main().

Wenn Sie müssen andere threads zu tun, hintergrund-Operationen in Ihrer Anwendung, Sie laichen können Sie aus der main().Eben sich erinnern Sie zu set Thread.IsBackground auf True, so dass Sie sterben werden, wenn der Haupt - / GUI-thread beendet wird.Sonst werden Sie haben zu arrangieren zu beenden alle Ihre anderen threads sich, oder Sie halten Ihre Anwendung lebendig (aber ohne GUI), wenn der Haupt-thread beendet wird.

Ich habe einen Artikel veröffentlicht, der auf dem splash-screen einbinden in die Anwendung bei codeproject.Es ist multithreaded und möglicherweise von Interesse sind

Noch ein Splash Screen in C#

private void MainForm_Load(object sender, EventArgs e)
{
     FormSplash splash = new FormSplash();
     splash.Show();
     splash.Update();
     System.Threading.Thread.Sleep(3000);
     splash.Hide();
}

Ich habe diese aus dem Internet irgendwo, aber kann nicht scheinen, um es wieder zu finden.Einfach, aber dennoch effektiv.

Ich mag Aku beantworten eine Menge, aber der code ist für C# 3.0 und oben, da es verwendet eine lambda-Funktion.Für Menschen benötigen, um mit dem code in C# 2.0, hier ist der code mit anonymen Delegaten anstelle der lambda-Funktion.Sie müssen eine oberste winform genannt formSplash mit FormBorderStyle = None.Die TopMost = True parameter der form ist wichtig, weil die splash-Bildschirm Aussehen könnte, wie es erscheint, dann verschwindet schnell, wenn es nicht die oberste.Ich habe auch wählen StartPosition=CenterScreen so wie es aussieht, was eine professionelle app machen würde mit einem splash-screen.Wenn Sie möchten, eine noch coolere Wirkung, Sie verwenden können die TrasparencyKey Eigenschaft, um eine unregelmäßig geformte splash-Bildschirm.

private void formMain_Load(object sender, EventArgs e)
  {

     Hide();
     bool done = false;
     ThreadPool.QueueUserWorkItem(delegate
     {
       using (formSplash splashForm = new formSplash())
       {
           splashForm.Show();
           while (!done)
              Application.DoEvents();
           splashForm.Close();
       }
     }, null);

     Thread.Sleep(2000);
     done = true;
     Show();
  }

Ich Stimme mit den anderen Antworten empfehlen WindowsFormsApplicationBase.In meiner Erfahrung, es kann langsam Ihre app.Um genau zu sein, während es läuft Konstruktor des Formulars parallel mit der splash-Bildschirm angezeigt wird, verschieben Sie Ihre form Dargestellt event.

Erwägen Sie eine app (ohne splashs Bildschirm) mit einem Konstruktor, der dauert 1 Sekunde, und einen event-handler auf Gezeigt, dass dauert 2 Sekunden.Diese app ist nutzbar nach 3 Sekunden.

Aber angenommen, Sie installieren ein splash-screen mit WindowsFormsApplicationBase.Sie denken vielleicht MinimumSplashScreenDisplayTime 3 Sekunden ist vernünftig und wird nicht langsam Ihre app.Aber, versuchen Sie, Ihre app wird nun 5 Sekunden, um zu laden.


class App : WindowsFormsApplicationBase
{
    protected override void OnCreateSplashScreen()
    {
        this.MinimumSplashScreenDisplayTime = 3000; // milliseconds
        this.SplashScreen = new Splash();
    }

    protected override void OnCreateMainForm()
    {
        this.MainForm = new Form1();
    }
}

und

public Form1()
{
    InitializeComponent();
    Shown += Form1_Shown;
    Thread.Sleep(TimeSpan.FromSeconds(1));
}

void Form1_Shown(object sender, EventArgs e)
{
    Thread.Sleep(TimeSpan.FromSeconds(2));
    Program.watch.Stop();
    this.textBox1.Text = Program.watch.ElapsedMilliseconds.ToString();
}

Fazit:nicht verwenden WindowsFormsApplicationBase wenn Ihre app-handler auf der Slown Ereignis.Schreiben Sie besseren code, dass läuft die splash parallel an den Konstruktor der Gezeigten Veranstaltung.

Eigentlich mutlithreading ist hier nicht notwendig.

Lassen Sie Ihre business-Logik, die ein Ereignis generieren, wenn Sie möchten update-splash-Bildschirm.

Dann lassen Sie Ihrer form update ein splash-Bildschirm entsprechend der Methode süchtig-Event-Handler.

Zu unterscheiden updates können Sie entweder Feuer verschiedene Ereignisse oder Daten in eine Klasse geerbt von EventArgs.

Auf diese Weise können Sie schön ändern splash-Bildschirm ohne multithreading Kopfschmerzen.

Eigentlich mit diesem können Sie auch unterstützen, wie z.B. gif-Bild auf einem splash-form.In Auftrag für Sie zu arbeiten, Anruf-Anwendung.DoEvents() im handler:

private void SomethingChanged(object sender, MyEventArgs e)
{
    formSplash.Update(e);
    Application.DoEvents(); //this will update any animation
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top