In my Project I included a splash-screen.
For that i wrote below code in Login Window Contractor. The Splash Screen is working perfectly. But after login, the main page is opened. if it is closed, then login is opened.
In that the Splash Screen is cross the Login page. I don't want this.
How to do this: Splash Screen Shown only once in my project?
Help me...
public LogIn()
{
InitializeComponent();
Thread th = new Thread(new ThreadStart(Splash));
th.Start();
Thread.Sleep(3000);
th.Abort();
Thread.Sleep(1000);
}
private void Splash()
{
Welcome sp = new Welcome();
sp.ShowDialog();
}
private void Form1_Load(object sender, EventArgs e)
{
SplashScreen Splash = new SplashScreen();
Splash.Show();
}
if you want the SplashScreen to close after 3 Seconds then use a timer in the SplashScreen and after 3 Seconds user this.close()
You can possibly pass a boolean parameter which will instruct the Login Constructor to display or not to display the Splash Screen.
public LogIn(boolean splashOpened)
{
InitializeComponent();
if(!splashOpened) //If Splash Screen is not opened , Open it
{
Thread th = new Thread(new ThreadStart(Splash));
th.Start();
Thread.Sleep(3000);
th.Abort();
Thread.Sleep(1000);
}
}
private void Splash()
{
Welcome sp = new Welcome();
sp.ShowDialog();
}
private static Welcome sp;
public LogIn()
{
InitializeComponent();
if (sp == null)
{
Thread th = new Thread(new ThreadStart(Splash));
th.Start();
Thread.Sleep(3000);
th.Abort();
Thread.Sleep(1000);
}
}
private void Splash()
{
if (sp == null)
{
sp = new Welcome();
sp.ShowDialog();
}
}
Related
How to intercept app_closing or app_entering_background in WinUi 3 app.
In UWP apps we do have Application_EnteredBackground event , in which we can intercept app close, we use GetDeferral() to save data .
Is there any same kind of event in WinUI 3 apps, I need to save data on app close, or entering background.
Tried window_VisibilityChanged and window_Closed events, but not able to use GetDeferral().
Kindly help
Thanks in advance .
Noorul
Here is my test code for your reference, you can intercept the closing event.
(closing is executed before closed)
public sealed partial class MainWindow : Window
{
private AppWindow _appWindow;
public MainWindow()
{
this.InitializeComponent();
this.Closed += OnClosed;
_appWindow = GetAppWindowForCurrentWindow();
_appWindow.Closing += OnClosing;
}
private void OnClosed(object sender, WindowEventArgs e)
{
string btnText = myButton.Content.ToString();
}
private async void OnClosing(object sender, AppWindowClosingEventArgs e)
{
string btnText = myButton.Content.ToString();
e.Cancel = true; //Cancel close
//Otherwise, the program will not wait for the task to execute, and the main thread will close immediately
//await System.Threading.Tasks.Task.Delay(5000); //wait for 5 seconds (= 5000ms)
Func<bool> funcSaveData = () =>
{
//perform operations to save data here
return true;
};
var funResult = await Task.Run(funcSaveData);
this.Close(); //close
}
private AppWindow GetAppWindowForCurrentWindow()
{
IntPtr hWnd = WindowNative.GetWindowHandle(this);
WindowId myWndId = Win32Interop.GetWindowIdFromWindow(hWnd);
return AppWindow.GetFromWindowId(myWndId);
}
private void myButton_Click(object sender, RoutedEventArgs e)
{
myButton.Content = "Clicked";
}
}
I have a SplashScreen that should be shown in front of all other windows in the application.
Since it is a SplashScreen, this cannot be modal dialog. Instead, this should be shown by mean of other thread.
I create the splash screen this way:
SplashScreenForm = new SplashScreen(mainForm);
// SplashScreenForm.TopMost = true;
And to show it, I am using this call, called from a different thread:
Application.Run(SplashScreenForm);
If I uncomment SplashScreenForm.TopMost = true, the splash is shown on top of other windows, even on top of windows belonging to different applications.
If you want to know how the thread is created:
public void ShowSplashScreen()
{
SplashScreenThread = new Thread(new ThreadStart(ShowForm));
SplashScreenThread.IsBackground = true;
SplashScreenThread.Name = "SplashScreenThread";
SplashScreenThread.Start();
}
private static void ShowForm()
{
Application.Run(SplashScreenForm);
}
How can I do it?
Something like:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Thread splashThread = new Thread(new ThreadStart(
delegate
{
splashForm = new SplashForm();
Application.Run(splashForm);
}
));
splashThread.SetApartmentState(ApartmentState.STA);
splashThread.Start();
// Load main form and do lengthy operations
MainForm mainForm = new MainForm();
mainForm.Load += new EventHandler(mainForm_Load);
Application.Run(mainForm);
}
Then later after time-consuming operations are ended:
static void mainForm_Load(object sender, EventArgs e)
{
if (splashForm == null)
return;
splashForm.Invoke(new Action(splashForm.Close));
splashForm.Dispose();
splashForm = null;
}
This will start your splash screen before your main form and only dismiss it when the lengthy operations are completed in mainForm_Load.
You can try calling function SetForegroundWindow(HWND) from WinAPI :
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
// somewhere in the code :
SetForegroundWindow(SplashScreenForm.Handle);
This is what I have got:
Thread t = new Thread(new ThreadStart(LoginForm));
t.Start();
Thread.Sleep(7500);
t.Abort();
InitializeComponent();
public void LoginForm()
{
Application.Run(new frmLoginForm());
}
How can I make the thread wait until the form closes before aborting the thread.
You can use ShowDialog() method to display the form, here is the MSDN
Or
Better to Declare Thread as public and only abort the Thread in the form closing event
Thread t = new Thread(new ThreadStart(LoginForm));
t.Start();
InitializeComponent();
public void LoginForm()
{
LoginForm frmLogin=new LoginForm();
DialogResult dr = frmLogin.ShowDialogue();
if (dr == DialogResult.Yes)
{
t.Abort();
}
}
and in the form closing event set the DialogResult property as
this.DialogResult = DialogResult.Yes;
You can try something like this,
var frmLogin = new FrmLogin();
if (frmLogin.ShowDialog() == DialogResult.OK)
{
Application.Run(new frmMainForm());
}
and in you frmLogin if login is OK then set the from dialog result as DialogResult.OK
Continuing SumeshK's solution, I will take lil different approach:
public void SomeMethod()
{
Thread t = new Thread(new ThreadStart(LoginForm));
t.Start();
t.Join();
InitializeComponent();
}
public void LoginForm()
{
LoginForm frmLogin=new LoginForm();
frmLogin.ShowDialog();
}
The method ShowDialog itself will block your thread from terminating/finishing. This should work. But I doubt about the InitializeComponent() method. what is it for?
I am working on C# win form application.My problem is when i click on menu i created one separate thread which is showing the progress(splash progress form). When i abort thread, progress form still display..! but when i move mouse pointer over the form it disappear
immediately..!
Following is my code
Thread progressThread = new Thread(() => Application.Run(new frmOperationProgress()));
progressThread.IsBackground = true;
progressThread.Start();
//Some work
progressThread.Abort();
How to close this progress form object in c#
The problem is using Abort - it's not generally recommended because there is no guarantee that it's going to do what you expect (in your case hide the form).
Best to add proper cancellation support into your thread and handle hiding the splash screen directly.
Please never ever use Abort(). This kind of work is best done trough BackgroundWorker; if you insist on Thread
Try:
var form = new frmOperationProgress();
Thread progressThread = new Thread(() => Application.Run(form));
progressThread.IsBackground = true;
progressThread.Start();
//Some work
form.ExternalClose();
Where ExternalClose is method of form like this:
public void ExternalClose() {
if (InvokeRequired) {
Invoke(new MethodInvoker(() => { ExternalClose(); }));
} else {
Close();
}
}
Solution using BackgroundWorker:
In backround worker you have to do UI stuff in ProgressChanged event (which is running in UI thread) and do the dirty work in DoWork event (background thread).
FormMain.cs: (Form with single BackgroundWorker control, named "backgroundWorker1", with wired up events backgroundWorker1_DoWork, backgroundWorker1_ProgressChanged and WorkerReportsProgress set to true)
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
namespace ConsoleApplication1 {
public partial class FormMain : Form {
private FormProgress m_Form;
public FormMain() {
InitializeComponent();
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
backgroundWorker1.ReportProgress(0, "hello");
Thread.Sleep(2000);
backgroundWorker1.ReportProgress(20, "world");
Thread.Sleep(2000);
backgroundWorker1.ReportProgress(40, "this");
Thread.Sleep(2000);
backgroundWorker1.ReportProgress(60, "is");
Thread.Sleep(2000);
backgroundWorker1.ReportProgress(80, "simple");
backgroundWorker1.ReportProgress(100, "end");
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) {
if (e.ProgressPercentage == 0 && m_Form == null) {
m_Form = new FormProgress();
m_Form.Show();
}
if (e.ProgressPercentage == 100 && m_Form != null) {
m_Form.Close();
m_Form = null;
return;
}
var message = (string)e.UserState;
m_Form.UpdateProgress(e.ProgressPercentage, message);
}
}
}
Where FormProgress is simple form with ProgressBar progressBar1 and Label label1 and one extra method:
public void UpdateProgress(int percentage, string message) {
this.progressBar1.Value = percentage;
this.label1.Text = message;
}
You can just close your form and the thread (which is blocked by the message loop of that form) will be ended naturally:
var yourForm = new frmOperationProgress();
//Start it
Thread progressThread = new Thread(() => Application.Run(yourForm));
progressThread.IsBackground = true;
progressThread.Start();
//....
//close it
yourForm.Invoke((Action)(() => yourForm.Close()));
I am loading MainWindow in App_Startup (). I wanted to show the progress bar while loading the window. But it is not working :
void App_Startup(object sender, StartupEventArgs e)
{
Thread bootStrapThread = new Thread(new ThreadStart(runBootStrapProcess));
bootStrapThread.SetApartmentState(ApartmentState.STA);
bootStrapThread.IsBackground = true;
bootStrapThread.Start();
_loadingProgressBar = new loadingProgressBar();
_loadingProgressBar.ShowDialog();
}
I want to load the window from thread :
void runBootStrapProcess()
{
MetadataReader mr = new MetadataReader();
if (currentVersionNo.Equals(remoteVersionNo))
{
Application.Current.Shutdown();
}
else
{
MainWindow mw = new MainWindow();
mw.Show();
}
_loadingProgressBar.ShouldCloseNow = true;
}
You can try this:
void runBootStrapProcess() {
MetadataReader mr = new MetadataReader();
if (currentVersionNo.Equals(remoteVersionNo)) {
Application.Current.Shutdown();
} else {
System.Windows.Application.Current.Dispatcher.BeginInvoke(
new Action(
() => {
MainWindow mw = new MainWindow();
mw.Show();
}));
}
_loadingProgressBar.ShouldCloseNow = true;
}
You basically from the thread when you want to show the window send it to the main application thread. This thus stops the application from closing down when the thread exits since the MainWindow is Shown from the main thread.
I suspect the window is missing the message pump since the WPF Application class with its Dispatcher is running on a different STA Thread