Showing invisible modal form

  • Thread starter Thread starter Dmitry Shaporenkov
  • Start date Start date
D

Dmitry Shaporenkov

Hi all,

in my application I'm showing a modal dialog indicating
the progress of background process. I would like the
progress indicator to appear not immediately after the
background process starts, but some seconds later. The
purpose is to avoid window winking in case if the process
takes very little time. So, my question is:

how to show a modal but invisible form?

Currently I'm using the Form.Opacity property to achieve
this. After background process starts, I do ShowDialog
with Opacity = 0, and set Opacity = 1 after some time if
the process is still executing. But I wonder about
portability of this approach, and I'd prefer more
reliable way.

Thanks,
Dmitry
 
Override the Show or ShowDialog method in your Form and can implement your
own functionality. Here's a sample that uses the System.Threading namespace
to start a thread to do some work. When the work is done it sets a wait
handle and the function returns. It's tricky with a modal form because you
have to wait for the process to complete before showing the form, but it can
be done.

This is even more desirable as it shouldn't block the application until the
work is actually completed. --- I love .NET!

Form1:

Form2 frm = new Form2();
MessageBox.Show(frm.ShowDialog().ToString());



Form2:

bool complete = false;

public new DialogResult ShowDialog()
{
Visible = false;
Thread t = new Thread(new ThreadStart(this.Start));
t.Start();
while(!complete)
{
Application.DoEvents();
}
return base.ShowDialog();
}

private void Start()
{
for (int i = 0; i < 1000000; i++) // do some work here.
{
Application.DoEvents();
}
complete = true;
}


HTH,
Eric Cadwell
http://www.origincontrols.com
 
Eric, thanks for your reply.
-----Original Message-----
Override the Show or ShowDialog method in your Form and can implement your
own functionality. Here's a sample that uses the System.Threading namespace
to start a thread to do some work. When the work is done it sets a wait
handle and the function returns. It's tricky with a modal form because you
have to wait for the process to complete before showing the form, but it can
be done.

This is even more desirable as it shouldn't block the application until the
work is actually completed. --- I love .NET!

However, I _do_ want to block the application during the
background process execution - regardless of the progress
indicator is visible or not. But if I call DoEvents in
the overriden ShowDialog, the user's input can be
accepted, and this is not the thing I'd like to happen,
because the background process is unable to handle these
changes.
 
Dmitry,

You can replace the DoEvents call with Thread.Sleep or use a
ManualResetEvent instead. I tried this first, but thought it might be
undesirable to block the main thread.

ManualResetEvent mre = new ManualResetEvent(false);

public new DialogResult ShowDialog()
{
Visible = false;
Thread t = new Thread(new ThreadStart(this.Start));
t.Start();
mre.WaitOne();

return base.ShowDialog();
}


private void Start()
{
for (int i = 0; i < 100; i++) // do some work here.
{
Thread.Sleep(50);
}
mre.Set();
}

HTH,
Eric Cadwell
http://www.origincontrols.com
 
Eric,

thanks for this idea. Currently I'm using System.Windows.Forms.Timer to
delay appearance of the progress indicator, so I cannot wait on event,
because I need to process messages in order to get timer notification.

It seems that the ideal solution is very complex. I _need_ to process
messages (like paint messages) in the interval between background
process start and progress indicator appearance, but I need to block
user input at the same time. So, I should define a soft of custom
message filter to block messages like WM_KEYDOWN and pass WM_PAINT.

You see now why I'm calling about a way to show modal invisible form -
it does all I need to do. If there were such a method, I'd use code like
following:

public void Progress.Start ()
{
process.Run ();
progressBar.ShowDialogInvisible (); // hypothetic method
visibleTimer.Start ();
}

void visibleTimer_Click ()
{
if (process is still running)
{
progressBar.Visible = true;
visibleTimer.Stop ();
}
}

void process_Finish ()
{
visibleTimer.Stop ();
progressBar.Hide ();
}
 
Back
Top