Showing up DataProcessing on SplashScreen Label c# - c#

The screen is already finished I used the Devexpress SplashScreen. It opens at the beginning and closes when all data is loaded until the main application opens. Now my question is how to get the data loaded in the background into a label so that the user sees something happening.

Check out SplashScreenManager.SendCommand for communication between the application and the splash screen
Form Code
private void btnShowSplashScreen_Click(object sender, EventArgs e) {
// Open a Splash Screen
SplashScreenManager.ShowForm(this, typeof(SplashScreen1), true, true, false);
// The splash screen will be opened in a separate thread. To interact with it, use the SendCommand method.
for (int i = 1; i <= 100; i++) {
SplashScreenManager.Default.SendCommand(SplashScreen1.SplashScreenCommand.SetProgress, i);
//To process commands, override the SplashScreen.ProcessCommand method.
Thread.Sleep(25);
}
// Close the Splash Screen.
SplashScreenManager.CloseForm(false);
}
Splash code
public override void ProcessCommand(Enum cmd, object arg) {
base.ProcessCommand(cmd, arg);
SplashScreenCommand command = (SplashScreenCommand)cmd;
if (command == SplashScreenCommand.SetProgress) {
int pos = (int)arg;
progressBarControl1.Position = pos;
}
}
public enum SplashScreenCommand {
SetProgress,
Command2,
Command3
}

Related

Time delay before redirecting [duplicate]

I need to show splash screen on my application start for few seconds. Does anybody know how to implement this?
Will be much appreciate for the help.
First, create your splash screen as a borderless, immovable form with your image on it, set to initially display at the center of the screen, colored the way you want. All of this can be set from within the designer; specifically, you want to:
Set the form's ControlBox, MaximizeBox, MinimizeBox and ShowIcon properties to "False"
Set the StartPosition property to "CenterScreen"
Set the FormBorderStyle property to "None"
Set the form's MinimumSize and MaximumSize to be the same as its initial Size.
Then, you need to decide where to show it and where to dismiss it. These two tasks need to occur on opposite sides of the main startup logic of your program. This could be in your application's main() routine, or possibly in your main application form's Load handler; wherever you're creating large expensive objects, reading settings from the hard drive, and generally taking a long time to do stuff behind the scenes before the main application screen displays.
Then, all you have to do is create an instance of your form, Show() it, and keep a reference to it while you do your startup initialization. Once your main form has loaded, Close() it.
If your splash screen will have an animated image on it, the window will need to be "double-buffered" as well, and you will need to be absolutely sure that all initialization logic happens outside the GUI thread (meaning you cannot have your main loading logic in the mainform's Load handler; you'll have to create a BackgroundWorker or some other threaded routine.
Here are some guideline steps...
Create a borderless form (this will be your splash screen)
On application start, start a timer (with a few seconds interval)
Show your Splash Form
On Timer.Tick event, stop timer and close Splash form - then show your main application form
Give this a go and if you get stuck then come back and ask more specific questions relating to your problems
simple and easy solution to create splash screen
open new form use name "SPLASH"
change background image whatever you want
select progress bar
select timer
now set timer tick in timer:
private void timer1_Tick(object sender, EventArgs e)
{
progressBar1.Increment(1);
if (progressBar1.Value == 100) timer1.Stop();
}
add new form use name "FORM-1"and use following command in FORM 1.
note: Splash form works before opening your form1
add this library
using System.Threading;
create function
public void splash()
{
Application.Run(new splash());
}
use following command in initialization like below.
public partial class login : Form
{
public login()
{
Thread t = new Thread(new ThreadStart(splash));
t.Start();
Thread.Sleep(15625);
InitializeComponent();
enter code here
t.Abort();
}
}
http://solutions.musanitech.com/c-create-splash-screen/
I wanted a splash screen that would display until the main program form was ready to be displayed, so timers etc were no use to me. I also wanted to keep it as simple as possible.
My application starts with (abbreviated):
static void Main()
{
Splash frmSplash = new Splash();
frmSplash.Show();
Application.Run(new ReportExplorer(frmSplash));
}
Then, ReportExplorer has the following:
public ReportExplorer(Splash frmSplash)
{
this.frmSplash = frmSplash;
InitializeComponent();
}
Finally, after all the initialisation is complete:
if (frmSplash != null)
{
frmSplash.Close();
frmSplash = null;
}
Maybe I'm missing something, but this seems a lot easier than mucking about with threads and timers.
create splash
private void timer1_Tick(object sender, EventArgs e)
{
counter++;
progressBar1.Value = counter *5;
// label2.Text = (5*counter).ToString();
if (counter ==20)
{
timer1.Stop();
this.Close();
}
}
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.GradientInactiveCaption;
this.ClientSize = new System.Drawing.Size(397, 283);
this.ControlBox = false;
this.Controls.Add(this.label2);
this.Controls.Add(this.progressBar1);
this.Controls.Add(this.label1);
this.ForeColor = System.Drawing.SystemColors.ControlLightLight;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.Name = "Splash";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.ResumeLayout(false);
this.PerformLayout();
Then in your application
sp = new Splash();
sp.ShowDialog();
The other answers here cover this well, but it is worth knowing that there is built in functionality for splash screens in Visual Studio: If you open the project properties for the windows form app and look at the Application tab, there is a "Splash screen:" option at the bottom. You simply pick which form in your app you want to display as the splash screen and it will take care of showing it when the app starts and hiding it once your main form is displayed.
You still need to set up your form as described above (with the correct borders, positioning, sizing etc.)
None of the other answers gave me exactly what I was looking for. Read on for my solution to the problem.
I want a splash screen to fade in from 0% opacity to 100% opacity while things boot up, with a minimum display time of 2000ms (to allow the full fade in effect to show). Once everything is ready, I want the splash screen to display for a further 500ms while the main screen displays behind the splash screen. Then I want the splash screen to go away, leaving the main screen running.
Note that I use the MVP pattern for winforms. If you don't use MVP, you will need to simplify the below example a little.
Long story short, you need to create an AppContext class that inherits from ApplicationContext. I have put this in my Program.cs as below:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new AppContext());
}
}
public class AppContext : ApplicationContext
{
private IMainPresenter _mainPresenter;
private bool _ready;
public AppContext()
{
_ready = false;
using (ISplashPresenter splashPresenter = new SplashPresenter(new SplashView()))
{
Stopwatch sw = Stopwatch.StartNew();
_mainPresenter = new MainPresenter(new MainView());
_mainPresenter.Closed += MainPresenter_Closed;
new Thread(() =>
{
// !!! Do work here !!!
if (sw.ElapsedMilliseconds < 2000)
Thread.Sleep(2000 - (int)sw.ElapsedMilliseconds);
_ready = true;
})
.Start();
while (!_ready)
{
Application.DoEvents();
Thread.Sleep(1);
}
_mainPresenter.Show();
_ready = false;
new Thread(() =>
{
Thread.Sleep(500);
_ready = true;
})
.Start();
while (!_ready)
{
Application.DoEvents();
Thread.Sleep(1);
}
}
}
private void MainPresenter_Closed(object sender, EventArgs e)
{
ExitThread();
}
}
There are several implementation specific details that I haven't gone into here, such as ISplashPresenter implementing IDisposable and exactly how the fade in is managed; if enough people request it I will edit this answer to include a complete example.
First you should create a form with or without Border (border-less is preferred for these things)
public class SplashForm : Form
{
Form _Parent;
BackgroundWorker worker;
public SplashForm(Form parent)
{
InitializeComponent();
BackgroundWorker worker = new BackgroundWorker();
this.worker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.worker _DoWork);
backgroundWorker1.RunWorkerAsync();
_Parent = parent;
}
private void worker _DoWork(object sender, DoWorkEventArgs e)
{
Thread.sleep(500);
this.hide();
_Parent.show();
}
}
At Main you should use that
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new SplashForm());
}
}
Maybe a bit late to answer but i would like to share my way.
I found an easy way with threads in the main program for a winform application.
Lets say you have your form "splashscreen" with an animation, and your "main" which has all your application code.
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Thread mythread;
mythread = new Thread(new ThreadStart(ThreadLoop));
mythread.Start();
Application.Run(new MainForm(mythread));
}
public static void ThreadLoop()
{
Application.Run(new SplashScreenForm());
}
In your main form in the constructor:
public MainForm(Thread splashscreenthread)
{
InitializeComponent();
//add your constructor code
splashscreenthread.Abort();
}
This way the splashscreen will last just the time for your main form to load.
Your splashcreen form should have his own way to animate/display information.
In my project my splashscreen start a new thread, and every x milliseconds it changes his main picture to another which is a slightly different gear, giving the illusion of a rotation.
example of my splashscreen:
int status = 0;
private bool IsRunning = false;
public Form1()
{
InitializeComponent();
StartAnimation();
}
public void StartAnimation()
{
backgroundWorker1.WorkerReportsProgress = false;
backgroundWorker1.WorkerSupportsCancellation = true;
IsRunning = true;
backgroundWorker1.RunWorkerAsync();
}
public void StopAnimation()
{
backgroundWorker1.CancelAsync();
}
delegate void UpdatingThreadAnimation();
public void UpdateAnimationFromThread()
{
try
{
if (label1.InvokeRequired == false)
{
UpdateAnimation();
}
else
{
UpdatingThreadAnimation d = new UpdatingThreadAnimation(UpdateAnimationFromThread);
this.Invoke(d, new object[] { });
}
}
catch(Exception e)
{
}
}
private void UpdateAnimation()
{
if(status ==0)
{
// mypicture.image = image1
}else if(status ==1)
{
// mypicture.image = image2
}
//doing as much as needed
status++;
if(status>1) //change here if you have more image, the idea is to set a cycle of images
{
status = 0;
}
this.Refresh();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
while (IsRunning == true)
{
System.Threading.Thread.Sleep(100);
UpdateAnimationFromThread();
}
}
Hope this will help some people.
Sorry if i have made some mistakes. English is not my first language.
Here is the easiest way of creating a splash screen:
First of all, add the following line of code before the namespace in Form1.cs code:
using System.Threading;
Now, follow the following steps:
Add a new form in you application
Name this new form as FormSplashScreen
In the BackgroundImage property, choose an image from one of your folders
Add a progressBar
In the Dock property, set it as Bottom
In MarksAnimationSpeed property, set as 50
In your main form, named as Form1.cs by default, create the following method:
private void StartSplashScreen()
{
Application.Run(new Forms.FormSplashScreen());
}
In the constructor method of Form1.cs, add the following code:
public Form1()
{
Thread t = new Thread(new ThreadStart(StartSplashScreen));
t.Start();
Thread.Sleep(5000);
InitializeComponent();//This code is automatically generated by Visual Studio
t.Abort();
}
Now, just run the application, it is going to work perfectly.
Here's my 2023 take on a 2011 question.
Over time, I've done this many times in many ways. The approach that currently use:
Force the main form Handle creation so that the message that creates the splash can be posted into the main form's message queue using BeginInvoke. This allows the main form ctor to return. Ordinarily the handle (the native hWnd) doesn't come into existence until it's shown. Therefore, it needs to be coerced while it's still hidden.
Override the SetVisibleCore() preventing the main window from becoming visible until the Splash has finished processing.
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
Debug.Assert(!IsHandleCreated, "Expecting handle is not yet created.");
// Ordinarily we don't get the handle until
// window is shown. But we want it now.
_ = Handle;
Debug.Assert(IsHandleCreated, "Expecting handle exists.");
// Call BeginInvoke on the new handle so as not to block the CTor.
BeginInvoke(new Action(()=> execSplashFlow()));
}
protected override void SetVisibleCore(bool value) =>
base.SetVisibleCore(value && _initialized);
bool _initialized = false;
private void execSplashFlow()
{
using (var splash = new SplashForm())
{
splash.ShowDialog();
}
_initialized= true;
WindowState = FormWindowState.Maximized;
Show();
}
}
Splash Example
The async initialization can be performed in the Splash class itself or it can fire events causing the main app to do things. Either way, when it closes itself the main form will set the _initialized bool to true and it is now capable of becoming visible.
public partial class SplashForm : Form
{
public SplashForm()
{
InitializeComponent();
StartPosition = FormStartPosition.CenterScreen;
FormBorderStyle = FormBorderStyle.None;
}
protected async override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
if (Visible)
{
labelProgress.Text = "Updating installation...";
progressBar.Value = 5;
await Task.Delay(1000);
progressBar.Value = 25;
// SIMULATED background task like making an API call or loading a
// database (long-running task that doesn't require the UI thread).
labelProgress.Text = "Loading avatars...";
await Task.Delay(1000);
labelProgress.Text = "Fetching game history...";
progressBar.Value = 50;
await Task.Delay(1000);
labelProgress.Text = "Initializing scenario...";
progressBar.Value = 75;
await Task.Delay(1000);
labelProgress.Text = "Success!";
progressBar.Value = 100;
await Task.Delay(1000);
DialogResult= DialogResult.OK;
}
}
}
Try this code
public partial class ssplashscreen : Form
{
public ssplashscreen()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
progressBar1.Increment(1);
if (progressBar1.Value == 100)
{
timer1.Stop();
this.Hide();
Form frm = new login();
frm.Show();
}
}
}
Try This:
namespace SplashScreen
{
public partial class frmSplashScreen : Form
{
public frmSplashScreen()
{
InitializeComponent();
}
public int LeftTime { get; set; }
private void frmSplashScreen_Load(object sender, EventArgs e)
{
LeftTime = 20;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
if (LeftTime > 0)
{
LeftTime--;
}
else
{
timer1.Stop();
new frmHomeScreen().Show();
this.Hide();
}
}
}
}

UWP StoreContext provides inaccurate information in RELEASE version

I have an app, published in Windows Store and the app has a trial version. But recently the trial version provides the full version somehow.
When I debugged the code, it shows that the following piece of code gets called twice in the release version and once it says that Trial is true and secondly it says Trial is false.
if (storeContext == null)
{
storeContext = StoreContext.GetDefault();
}
appLicense = await storeContext.GetAppLicenseAsync();
if (appLicense.IsActive)
{
if (appLicense.IsTrial)
{
isTrial = true;
}
else
{
isTrial = false;
}
}
When I debug the code in Release version it appLicense.IsTrial gets evaluated two times and that's how it produces two different results. Is it a bug? Should I tell Microsoft about this? Or is it just related to me somehow? If you try my app from store here you can probably see that it provides full access to the application and that the search is available to use while it's disabled in Trial version. Please help me with this.
Update:
The ExtendedSplash code:
public sealed partial class ExtendedSplash : Page
{
internal Rect splashImageRect; // Rect to store splash screen image coordinates.
private SplashScreen splash; // Variable to hold the splash screen object.
internal bool dismissed = false; // Variable to track splash screen dismissal status.
internal Frame rootFrame;
// Define methods and constructor
public ExtendedSplash(SplashScreen splashscreen, bool loadState)
{
InitializeComponent();
// Listen for window resize events to reposition the extended splash screen image accordingly.
// This ensures that the extended splash screen formats properly in response to window resizing.
Window.Current.SizeChanged += new WindowSizeChangedEventHandler(ExtendedSplash_OnResize);
splash = splashscreen;
if (splash != null)
{
// Register an event handler to be executed when the splash screen has been dismissed.
splash.Dismissed += new TypedEventHandler<SplashScreen, Object>(DismissedEventHandler);
// Retrieve the window coordinates of the splash screen image.
splashImageRect = splash.ImageLocation;
//PositionImage();
// If applicable, include a method for positioning a progress control.
//PositionRing();
}
// Create a Frame to act as the navigation context
rootFrame = new Frame();
}
void PositionImage()
{
//extendedSplashImage.SetValue(Canvas.LeftProperty, splashImageRect.X);
//extendedSplashImage.SetValue(Canvas.TopProperty, splashImageRect.Y);
//extendedSplashImage.Height = splashImageRect.Height;
//extendedSplashImage.Width = splashImageRect.Width;
}
void PositionRing()
{
splashProgressRing.SetValue(Canvas.LeftProperty, splashImageRect.X);// + (splashImageRect.Width * 0.5) - (splashProgressRing.Width * 0.5));
splashProgressRing.SetValue(Canvas.TopProperty, (splashImageRect.Y + splashImageRect.Height));// + splashImageRect.Height * 0.1));
}
// Include code to be executed when the system has transitioned from the splash screen to the extended splash screen (application's first view).
async void DismissedEventHandler(SplashScreen sender, object e)
{
dismissed = true;
// Complete app setup operations here...
await TrialManager.IsTrialLicense();
// this is the code that gets called to see the Trial / Purchase
DismissExtendedSplash();
}
async void DismissExtendedSplash()
{
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
// Navigate to mainpage
rootFrame.Navigate(typeof(IndexPage));
// Place the frame in the current Window
Window.Current.Content = rootFrame;
});
}
void ExtendedSplash_OnResize(Object sender, WindowSizeChangedEventArgs e)
{
// Safely update the extended splash screen image coordinates. This function will be executed when a user resizes the window.
if (splash != null)
{
// Update the coordinates of the splash screen image.
splashImageRect = splash.ImageLocation;
//PositionImage();
// If applicable, include a method for positioning a progress control.
//PositionRing();
}
}
void RestoreStateAsync(bool loadState)
{
if (loadState)
{
// code to load your app's state here
}
}
}

Is it safe to Invoke on a Dispatcher when the corresponding Window has been closed?

I have a window with that is shown to the user as a busy spinner when batch operations are being executed. An external class manages the batch operations and displays the busy spinner window when the list of operations takes longer than a specified amount of time.
class BatchOperationManager {
int timeToDelay = 1000;
void Execute()
{
BusyWindow window = new BusyWindow();
window.Loaded += BeginBatchOperations;
DelayOpening(window);
window.ShowDialog();
}
void BeginBatchOperations(object sender, EventArgs e)
{
var thread = new Thread(ExecuteBatchOperations);
thread.Start(sender);
}
void ExecuteBatchOperations(object window)
{
var busyWindow = (BusyWindow)window;
//do work
window.Dispatcher.Invoke(window.Close);
}
void DelayOpening(BusyWindow window)
{
window.Width = 0;
window.Height = 0;
Task.Delay(timeToDelay).ContinueWith(_ =>
{
window.Dispatcher.Invoke(window.EnlargeWindow);
});
}
}
window.EnlargeWindow resizes the window and centers it so that it is visible to the user.
My question is related to the body of Task.Delay.ContinuesWith: What happens to window if all of the work has been exhausted before the ContinuesWith body has been executed?
I've ran a few tests and everything appears to work. No exceptions are visibly thrown in the main thread. I think I am missing something critical here. Is there a cleaner approach?

Making a winforms 2.0 Splash Screen

What is the easiest way to fire a splash screen (Which disappears on its own) in a C# / .NET 2.0 winforms app? It looks like the VisualBasic assembly (which can be called from C# nonetheless) has a way to do this, but are there any simple examples?
Thanks
There's a detailed tutorial on Code Project which puts the splash screen on its own thread so the main app can get on with loading up.
Easiest way would be to create a form and allow it to kill itself after some time it is shown. But, things gets more complicated if you want this form to be able to display some application loading progress while application is initializing, and disappear for example 3 seconds after application is really ready for use.
Idea would include putting the splash screen on completely different thread from the main application. It's thread function should go like that:
static void ThreadFunc()
{
_splash = new Splash();
_splash.Show();
while (!_shouldClose)
{
Application.DoEvents();
Thread.Sleep(100);
if (new Random().Next(1000) < 10)
{
_splash.Invoke(new MethodInvoker(_splash.RandomizeText));
}
}
for (int n = 0; n < 18; n++)
{
Application.DoEvents();
Thread.Sleep(60);
}
if (_splash != null)
{
_splash.Close();
_splash = null;
}
}
Then, you can use this to show and hide it:
static public void ShowSplash()
{
_shouldClose = false;
Thread t = new Thread(ThreadFunc);
t.Priority = ThreadPriority.Lowest;
t.Start();
}
internal static void RemoveSplash()
{
_shouldClose = true;
}

How do I get custom dialog close without showing graphics artifacts?

I have a custom windows modal form with the following event code:
private void btnCancel_Click(object sender, EventArgs e)
{
Close();
_result = DialogResult.OK;
}
The problem is when I click OK, that triggers some process-intensive stuff (report generation) and the form becomes partially drawn on the screen. It's like the report generation is taking precedence over the window refresh. Is there something else I need to do in order to get it to disappear before the process-intensive code? This will most definitely annoy my users.
EDIT #1:
I'm trying to work Tergiver's method and pass in the dialog owner to ShowDialog. For my case, the calling method is not a form. So, I'm trying to create a IWin32Owner from the process's main window handle so that I can pass it into the ShowDialog method.
public class WindowWrapper : System.Windows.Forms.IWin32Window
{
public WindowWrapper(IntPtr handle)
{
_hwnd = handle;
}
public IntPtr Handle
{
get { return _hwnd; }
}
private IntPtr _hwnd;
}
// In calling method
ShowDialog(new WindowWrapper(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle));
However, the dialog owner is still not set after the call to ShowDialog. I stepped into the WindowWrapper and the handle is non-zero. Any more ideas as to how to get the current process's active form?
EDIT #2
I'm now using the following code to retrieve the active form and then calling Owner.Refresh() in the OnFormClosed event.
public static Form GetActiveForm()
{
// Returns null for an MDI app
Form activeForm = Form.ActiveForm;
if (activeForm == null)
{
FormCollection openForms = Application.OpenForms;
for (int i= 0; i < openForms.Count && activeForm == null; ++i)
{
Form openForm = openForms[i];
if (openForm.IsMdiContainer)
{
activeForm = openForm.ActiveMdiChild;
}
}
}
return activeForm;
}
// In code opening dialog.
ShowDialog(GetActiveForm());
The obvious answer is not to do process-intensive code on the UI thread.
Use a BackgroundWorker or the ThreadPool to do the task.
Added
If you insist on doing it on the UI thread, you could use this.Owner.BeginInvoke to execute code after this closes.

Categories