views:

329

answers:

1

I have a borderless WinForms app.

The main window creates other forms (simple dialogs where I can click yes or no) with ShowDialog(). Every created dialog is not visible in the taskbar, my app has only one taskbar entry that focuses my app (and if a dialog is open that one is focused). If I use ALT+TAB to cycle to all open windows I only see one entry, too.

However, If the dialog is created while my app doesn't have the focus (for example the user starts a long running task, starts to work on something else and while being in the background, my app shows a dialog "Task done...") and I want to go back to my app, things are getting strange.

  • If I click on the taskbar to focus my app, the main window is focused (not the dialog).
  • I can't use the main window (because there is still an open modal dialog).
  • Windows 7 ALT-TAB preview shows the Dialog while taskbar mouseover preview shows the main window (In normal behavior both show the dialog in front of the main window).
  • The only way to make my app usable again is to ALT-TAB to the entry and close the modal dialog.
  • If I use ALT-TAB only the dialog is brought to the front and the main window is still in the background

Is there a way to prevent that from happening? I know what to do, but most customers think the app crashed since the main window doesn't respond.

Update:

The solution is to pass the top level window to the ShowDialog() method (in most cases and if used in a form that would be the "this").

Since I didn't wanted to refactor my entire code, and all my forms inherit from "MyCustomFormBase" here is a little solution that works very well.

Public Class MyCustomFormBase

    Public Shared Property ApplicationMainForm() As Form
        Get
            Return _applicationMainform
        End Get
        Set(ByVal value As Form)
            _applicationMainform = value
        End Set
    End Property
    Private Shared _applicationMainform As Form

    Public Shadows Function ShowDialog() As DialogResult
        If MyCustomFormBase.ApplicationMainForm IsNot Nothing Then
            Return MyBase.ShowDialog(MyCustomFormBase.ApplicationMainForm)
        Else
            Return MyBase.ShowDialog()
        End If
    End Function

    Public Shadows Function ShowDialog(ByVal owner As IWin32Window) As DialogResult
        Return MyBase.ShowDialog(owner)
    End Function

End Class

In the constructor of the main window I use

MyCustomFormBase.ApplicationMainForm = Me

once. Helped me half a day refactoring ;)

+2  A: 

Have you tried passing a reference to the main window to ShowDialog calls?

// assuming this code is in the main form (so "this" refers to the main form)
DialogForm dialog = new DialogForm();
DialogResult result = dialog.ShowDialog(this);

Quote from the documentation of this overload:

This version of the ShowDialog method allows you to specify a specific form or control that will own the dialog box that is shown. If you use the version of this method that has no parameters, the dialog box being shown would be owned automatically by the currently active window of your application.

Fredrik Mörk
I propably used the method a thousand times and never noticed that there is an overload ;) Anyway that works. thx a lot.
SchlaWiener
+1, without the argument it will try to find one. The desktop window, if necessary.
Hans Passant