Thursday, March 20, 2014

Dealing with minimize of the application from Task Manager

There are some options to minimize a Windows application (in Windows 7) besides using of window control bar:
  • Show desktop button at the end of the notification area on the taskbar,
  • Windows logo button + D combination,
  • Option Show the desktop from the context menu after right click on taskbar

Did you know that Task Manager is also able to minimize Windows application? It does it in a very forceful way. The scenario that is particularly interesting is when an application is showing a modal dialog. Normally it would be impossible to minimize such an application until the modal window is closed but that's not a problem for Task Manager.

When application that displays a modal dialog is minimized form Task Manager, the modal dialog is automatically closed and DialogResult.Cancel is returned from the ShowDialog method.
The dialog is of course not shown again on the restoration.

This is, by contrast, very different from the default behavior of the first three options where the modal window is reopened along with main application window. This is also not applicable for MessageBox which is always reopened.

Is your program prepared for that? I've seen applications that do heavy processing under the cover of modal dialog which is not expected to disappear until it finished its work.
This would be an example of worker modal window that is used sometimes:

 public partial class ModalWindow : Form
  {
    private readonly BackgroundWorker _bw = new BackgroundWorker();

    public ModalWindow()
    {
      InitializeComponent();
    }

    public void StartWorking()
    {
      _bw.DoWork += PerformLengthyAction;
      _bw.RunWorkerCompleted += (o, args) =>
      {
        DialogResult = DialogResult.OK;
        Close();
      };
      _bw.RunWorkerAsync();
    }

    private void PerformLengthyAction(object sender, DoWorkEventArgs doWorkEventArgs)
    {
      Thread.Sleep(15000);
    }
  }

Or, in .NET 4.5 it may be following.

  public partial class ModalWindow : Form
  {
    public ModalWindow()
    {
      InitializeComponent();
    }

    public async void StartWorking()
    {
      var progress = new Progress<string>(text => textBoxLog.AppendText(text));
      await Task.Run(() => PerformLengthyAction(progress));
       DialogResult = DialogResult.OK;
       Close();
    }

    private void PerformLengthyAction(IProgress<string> progress)
    {
      progress.Report("Processing database entries... ");
      Thread.Sleep(5000);
      progress.Report("Done\n");
      progress.Report("Updating IP Cache... ");
      Thread.Sleep(5000);
      progress.Report("Done\n");
      progress.Report("Publishing configuration... ");
      Thread.Sleep(5000);
      progress.Report("Done\n");
    }
  }

It is invoked from main window like this:

  public partial class MainWindow : Form
  {
    private ModalWindow _processingDialog;
    public MainWindow()
    {
      InitializeComponent();
    }

    private void buttonForModalDialog_Click(object sender, EventArgs e)
    {
      _processingDialog = new ModalWindow {DialogResult = DialogResult.None};
      _processingDialog.StartWorking();
      _processingDialog.ShowDialog();
    }
  }

The solutions above is prone to minimization forced by Task Manager.
A quick fix would be to try to reopen the modal dialog on application restore:

  public partial class MainWindow : Form
  {
    ...
    private void MainWindow_Resize(object sender, EventArgs e)
    {
      TryToReopenProcessingDialog();
    }

    private void TryToReopenProcessingDialog()
    {
      if (_processingDialog.DialogResult == DialogResult.Cancel
          && WindowState != FormWindowState.Minimized)
        _processingDialog.ShowDialog();
    }
  }

1 comment:

  1. Hi there, thanks for sharing your expertise on these matter. It's really a big help for me and to others as well who is looking for top virtual assistant companies. Nice blog style too. Keep it up!

    ReplyDelete