Create a screensaver

The concept of the screen saver does not affect me as something complicated, but I am having problems so that the entire screen saver is painted.

Say I have two System.Windows.Forms.Form s: RealForm and SplashScreen. RealForm contains an initial graphical interface. During the RealForm loading process (that is, in the event handler for the Load event), RealForm creates a database connection and then checks the connection. This may take a few seconds, so before I do all this, I will try to set the splash screen like this:

 private void RealForm_Load(object sender, EventArgs e) { SplashScreen splash = new SplashScreen(); splash.Show(); loadAndCheckDatabase(); splash.Close(); } 

The problem is that the splash screen is only partially rendered, and therefore it does not look like a large screen. Any idea why? What should I do?

For bonus points, does anyone know where to find an explanation for all the series of events that occur during the typical creation, use and destruction of forms? The above problem is probably due to the fact that I do not understand what is happening in the order of things or where you can connect to form events.


UPDATE Close, but not quite: look for a bit more advice. Here's the current code:

 private SplashScreen splash = new SplashScreen(); private void RealForm_Load(object sender, EventArgs e) { splash.Show(); BackgroundWorker worker = new BackgroundWorker(); worker.DoWork += new DoWorkEventHandler(worker_DoWork); worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler (worker_RunWorkerCompleted); worker.RunWorkerAsync(); this.Visible = false; } void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { splash.Close(); this.Visible = true; } void worker_DoWork(object sender, DoWorkEventArgs e) { loadAndCheckDatabase(); } 

Unfortunately, this.Visible = false does nothing, because it is automatically set to true in code that I do not control. So, to get around this, I put this.Visible = false in the handler for the Shown form Shown . However, as you can probably guess, you can still see the shape for a split second ... so this is not a very good solution.

Is there a way to wait for the workflow while I'm still in the load handler?

+4
source share
6 answers

You display a splash screen and check your database in the same thread. A thread can do only one at a time.

A quick and cheap way to fix this is to periodically loadAndCheckDatabase() call Application.DoEvents() . However, this is a cheap solution.

You really want to run loadAndCheckDatabase () in your own thread, BackgroundWorker is a good easy way to do this.

+9
source

Like me, you probably created this as an afterthought and don't want to go through all the features of redesigning your code to fit a multi-threaded architecture ...

First create a new form called SpashScreen, in the properties click BackgroundImage and import any image you want. Also set the FormBorderStyle parameter to None so that you cannot click the x icon 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 the progress bar or any fancy stuff, but I'm sure it can be changed.

+2
source

Try placing a call to loadAndCheckDatabase in a background thread by moving the screen saver to close or just closing it with a timer in the screen saver. When working in the background thread, all user interface functions will work without interruption.

+1
source

You must run the splash screen in another thread, which should allow it to draw correctly.

Look at here:

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

+1
source

Why, when starting the application, open a form that loads everything you need to load into the class, and then when it loads, open the main form and submit the class to it? Alternatively, you can use singleton to download everything.

In the program 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 the working code (this is just a 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())); } 
+1
source

You can use the wait 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 ie loadAndCheckDatabase Task processLongTask = loadAndCheckDatabase(); //wait for the task to be completed processLongTask.Wait(); splash.Close(); //... } 
-2
source

All Articles