How to run code when form is shown? - c#

I thought the Load event might help, but the following code just shows “Done” immediately.
public Form1()
{
InitializeComponent();
Load += new EventHandler(Form1_Load);
}
void Form1_Load(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(3000);
Text = "Done";
}
How do I make it Sleep after the form is shown?
Thanks.

There is a Shown event for a windows form. Check out: http://msdn.microsoft.com/en-us/library/system.windows.forms.form.shown.aspx
Or if you are lazy, here you go:
public Form1()
{
InitializeComponent();
Shown += Form1_Shown;
}
private void Form1_Shown(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(3000);
Text = "Done";
}
Enjoy.

I would suggest do not block a form, process something and after show in its title "Done", cause that what you want to do, I presume. This gives to the user blocked UI feeling, which is not good.
It's definitely better to show some temporary "Wait for..." form and on completion of the operation/calculation you perform, show your main form.
Much more UX focused design.

You could start a Timer in the Form1_Load method and link its Elapsed event to a method that displays the message.

Thread.Sleep(3000); in the Load event handler delays the form opening for 3 seconds. This why it does not work as you expect. A timer is the best solution.

Related

How to check when the timer tick event occurs

I need to make a splash screen that is visible for 5000 milliseconds before closing. I pass in 5000 to my SplashScreen form constructor and set timer1.Interval = time. I can't seem to find a straightforward answer online and I don't have much experience with timers. I assume that I need to show the splash screen, start the timer, check for when timer1.Tick occurs, and close the form but I don't know the syntax on how to do that.
private void Form1_Load(object sender, EventArgs e)
{
SplashScreen splash = new SplashScreen(5000, appLogo, "Text Editor", "Copyright (c) 2020", "John Doe");
splash.timer1.Enabled = true;
splash.ShowDialog();
splash.timer1.Start();
// Wait for Tick event to occur.....
splash.Close();
}
In your SplashScreen form, you need to define the Tick event:
timer1.Tick += new EventHandler(CloseForm);
That calls a method to close the form:
private void CloseForm(Object source, EventArgs eventArgs)
{
this.Close();
}

System.Windows.Forms.Timer And MessageBox

can someone please let me know why the System.Windows.Forms.Timer continues to show multiple message boxes? I thought that it is on GUI thread ... and therefore after the first messagebox the GUI thread should block. But this is not the case
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int nValue = 0;
void tmr_Tick(object sender, EventArgs e)
{
nValue++;
MessageBox.Show(nValue.ToString());
}
System.Windows.Forms.Timer tmr = new System.Windows.Forms.Timer();
private void btnStartTimer_Click(object sender, EventArgs e)
{
tmr.Interval = 500;
tmr.Enabled = true;
tmr.Tick += new EventHandler(tmr_Tick);
}
}
The MessageBox.Show() method includes (as all modal dialogs do) a message loop that continues to pump window messages.
Window messages are what allow a window to interact with the user (update itself, accept input, etc.), as well as what allows the Forms.Timer class to work.
If you want your Forms.Timer to stop ticking when the dialog is shown, you need to set the timer's Enabled property to false before you show the dialog.
In your Tick event stop the timer and then start again after MessageBox.Show like:
void tmr_Tick(object sender, EventArgs e)
{
tmr.Enabled = false;
nValue++;
MessageBox.Show(nValue.ToString());
tmr.Enabled = true;
}
The reason you are getting repeated MessgeBoxes is because your timer is continuing after showing the first MessageBox.
A message box does not block the GUI-Thread. It's as simple as that. You can interact with the message box, after all :)
Also: The internal workings of the timer are not clear, but I would guess that it runs on another thread and just returns on the GUI-Thread.

StatusLabel - how to reset, or allow status text to time out or fade away

I have a tabbed form with a StatusStrip at the bottom, which includes a StatusLabel. I want to use this status label for various actions ("1 record updated" etc). It is simple enough to create specific events to set the label's text property.
But how best to reset the status to blank? The user could perform any number of other operations where the status is no longer meaningful (going to another tab, clicking other buttons etc.).
It is not feasible to create all the possible events to reset the status message. Is there a way to incorporate some type of timer so that the message fades out after several seconds? Has anyone else found a good solution for this?
Is it truly important to clear the status though? There are plenty of products which will keep their status label unchanged until the next status event occurs. Visual Studio is a good example of this. It may be worth simplifying your scenario and taking this approach.
If you do want to clear the status after an event I think the most maintainable way to do this is with a Timer. Essentially clear after a few seconds when the status is set
Timer m_timer;
void SetStatus(string text) {
m_statusLabel.Text = text;
m_timer.Reset();
}
void OnTimerTick(object sender, EventArgs e) {
m_statusLabel.Text = "";
m_timer.Stop();
}
Yes a timer would work for this to clear it. Here is an example of one I've knocked together.
public partial class Form1 : Form
{
private System.Timers.Timer _systemTimer = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
_systemTimer = new System.Timers.Timer(500);
_systemTimer.Elapsed += _systemTimer_Elapsed;
}
void _systemTimer_Elapsed(object sender, ElapsedEventArgs e)
{
toolStripStatusLabel1.Text = string.Empty;
_systemTimer.Stop(); // stop it if you don't want it repeating
}
private void button1_Click(object sender, EventArgs e)
{
toolStripStatusLabel1.Text = "random text just as an example";
}
private void button2_Click(object sender, EventArgs e)
{
_systemTimer.Start();
}
}
Assume button1 is your action to update the status, and button2 is just a random way to start the timer (this can be however you want to start it, I've only used another button click as an example). After the set amount of time passes the status label will be cleared.

Opening A WinForm Programmatically In Another WinForm's Code

Happy Friday SO!
I'm building a multi-WinForm application and am having some troubles.
I have a main WinForm that stays open at all times. It hits a database every minute looking for changes, and if there is a change, it will open the second WinForm (this may seem like a stupid way to do things, but for my purpose, this is the best method).
Just sticking the following code into my Form1.cs doesn't do the trick:
Application.Run(new Form2());
Can you guys point me in the right direction? I have no idea where to turn.
Form2 form2 = new Form2();
form2.Show();
and to prevent a ton of forms being opened, maybe:
Form2 form2 = new Form2();
form2.ShowDialog();
#Comment:
A BackgroundWorker is used to keep your current UI Thread responsive. It was not designed to keep multiple forms pumping happily along. Look into running your intensive code as a Background thread within a ThreadPool.
If what you wish is to launch a long process and to show the progress to the user, for example just like when you have a progress bar or something alike, you should use a BackgroundWorker to do the job. Here's a simple example:
public partial class ProgressForm : Form {
// Assuming you have put all required controls on design...
// Allowing some properties to be exposed for progress update...
public properties MaximumProgress {
set {
progressBar1.Maximum = value;
}
public properties OverallProgress {
set {
progressBar1.Value = value;
}
}
public partial class MainForm : Form {
private BackgroundWorker backgroundWorker1;
private ProgressForm _pf;
public MainForm() {
InitializeComponent();
backgroundWorker1 = new BackgroundWorker();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.DoWork += backgroundWorker1_DoWork;
backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
}
// Assuming process starts on Button click.
private void button1_Click(object sender, EventArgs e) {
_pf = new ProgressForm();
_pf.MaximumProgress = number-of-elements-to-treat-returned-by-prevision-or-whatever-else;
// Launching the background workder thread.
backgroundWorker1.RunWorkerAsync(); // Triggering the DoWork event.
// Then showing the progress form.
_pf.ShowDialog();
}
private void backgroundWorker1_DoWork(object sender, EventArgs e) {
LaunchProcess();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) {
_pf.OverallProgress = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, EventArgs e) {
_pf.Close();
_pf.Dispose();
}
private void LaunchProcess() {
// Do some work here...
// Reporting progress somewhere within the processed task
backgroundWorker1.ReportProgress();
}
}
This is not a compileable code as its purpose is to illustrate the main idea.
Now, is this something alike you want to do?

ShowDialog, PropertyGrid and Timer problem

I have a strange bug, please, let me know if you have any clues about the reason.
I have a Timer (System.Windows.Forms.Timer) on my main form, which fires some updates, which also eventually update the main form UI. Then I have an editor, which is opened from the main form using the ShowDialog() method. On this editor I have a PropertyGrid (System.Windows.Forms.PropertyGrid).
I am unable to reproduce it everytime, but pretty often, when I use dropdowns on that property grid in editor it gets stuck, that is OK/Cancel buttons don't close the form, property grid becomes not usable, Close button in the form header doesn't work.
There are no exceptions in the background, and if I break the process I see that the app is doing some calculations related to the updates I mentioned in the beginning.
What can you recommend? Any ideas are welcome.
What's happening is that the thread timer's Tick method doesn't execute on a different thread, so it's locking everything else until it's done. I made a test winforms app that had a timer and 2 buttons on it whose events did this:
private void timer1_Tick(object sender, EventArgs e)
{
Thread.Sleep(6000);
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Start();
}
private void button2_Click(object sender, EventArgs e)
{
frmShow show = new frmShow();
show.ShowDialog(); // frmShow just has some controls on it to fiddle with
}
and indeed it blocked as you described. The following solved it:
private void timer1_Tick(object sender, EventArgs e)
{
ThreadPool.QueueUserWorkItem(DoStuff);
}
private void DoStuff(object something)
{
Thread.Sleep(6000);
}

Categories