Making a splash screen

前端 未结 6 1169
无人及你
无人及你 2021-01-06 06:29

The concept of a splash screen doesn\'t strike me as something that should be so complicated, but I\'m having trouble getting the whole splash screen painted.

Let\'s

相关标签:
6条回答
  • 2021-01-06 06:55

    Why not when you run the app open a form which loads whatever you need to load into a class, then when it's done loading, open your main form and send the class into it? Alternatively you can use a singleton to load everything.

    In your Program.cs:

        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new SplashScreen());
        }
    

    Then in SplashScreen:

        public SplashScreen()
        {
            InitializeComponent();
            LoadEverything();
            this.Visible = false;
            MainForm mainForm = new MainForm(LoadedClass);
            mainForm.ShowDialog();
            this.Close();
        }
    

    I need to update this:

    Here's working code (the above is just the concept).

        public SplashScreen()
        {
            InitializeComponent();
            _currentDispatcher = Dispatcher.CurrentDispatcher;
    
            // This is just for the example - start a background method here to call
            // the LoadMainForm rather than the timer elapsed
            System.Timers.Timer loadTimer = new System.Timers.Timer(2000);
            loadTimer.Elapsed += LoadTimerElapsed;
            loadTimer.Start();
        }
    
        public void LoadMainForm()
        {
            // Do your loading here
            MainForm mainForm = new MainForm();
    
            Visible = false;
            mainForm.ShowDialog();
            System.Timers.Timer closeTimer = new System.Timers.Timer(200);
            closeTimer.Elapsed += CloseTimerElapsed;
    
            closeTimer.Start();
        }
    
        private Dispatcher _currentDispatcher;
    
        private void CloseTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (sender is System.Timers.Timer && sender != null)
            {
                (sender as System.Timers.Timer).Stop();
                (sender as System.Timers.Timer).Dispose();
            }
            _currentDispatcher.BeginInvoke(new Action(() => Close()));
        }
    
        private void LoadTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (sender is System.Timers.Timer && sender != null)
            {
                (sender as System.Timers.Timer).Stop();
                (sender as System.Timers.Timer).Dispose();
            }
            _currentDispatcher.BeginInvoke(new Action(() => LoadMainForm()));
        }
    
    0 讨论(0)
  • 2021-01-06 07:00

    Try putting the call to loadAndCheckDatabase in a background thread, moving the close of the splash screen there, or simply closing it with a timer in the splash screen. With the work in a background thread, the all UI functions will be able to operate without interruption.

    0 讨论(0)
  • 2021-01-06 07:06

    You can use the await command with .Net Framework 4.5 Your form will not be visible until the task is completed

        private void YourForm_Load(object sender, EventArgs e)
        {
            //call SplashScreen form
            SplashScreen splash = new SplashScreen();
            splash.Show();
            Application.DoEvents();
            //Run your long task while splash screen is displayed i.e. loadAndCheckDatabase
            Task processLongTask = loadAndCheckDatabase();
            //wait for the task to be completed
            processLongTask.Wait();
            splash.Close();
    
            //...
        }
    
    0 讨论(0)
  • 2021-01-06 07:13

    You are displaying the splash screen and checking your database on the same thread. The thread can only do one thing at a time.

    A quick and cheap way to fix this is to have loadAndCheckDatabase() call Application.DoEvents() periodically. However that's a cheap fix.

    You really want to run loadAndCheckDatabase() on its own thread, a BackgroundWorker is a nice simple way to do this.

    0 讨论(0)
  • 2021-01-06 07:15

    Like me you probably created this as an afterthought and do not want to go through all the heck of redesigning your code to fit multi-threaded architecture...

    First create a new Form called SpashScreen, in the properties click on BackgroundImage and import whatever image you want. Also set FormBorderStyle to None so that you can't click on the x to close the screen.

        public Form1()
        {
            InitializeComponent();
    
            BackgroundWorker bw = new BackgroundWorker();
            bw.WorkerSupportsCancellation = true;
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.RunWorkerAsync();  // start up your spashscreen thread
            startMainForm();      // do all your time consuming stuff here  
            bw.CancelAsync();     // close your splashscreen thread  
        }
    
    
        private void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
    
            SplashScreen ss = new SplashScreen();
            ss.Show();
    
            while (!worker.CancellationPending) //just hangout and wait
            {
                Thread.Sleep(1000);
            }
    
            if (worker.CancellationPending)
            {
                ss.Close();
                e.Cancel = true;
            }
    
        }
    

    This does not support progress bar or any fancy stuff but I am sure it can be tweaked.

    0 讨论(0)
  • 2021-01-06 07:18

    You should be running the splash screen in a different thread, that should allow it to draw properly.

    Have a look here:

    http://www.codeproject.com/KB/cs/prettygoodsplashscreen.aspx

    0 讨论(0)
提交回复
热议问题