Question

I have a class library that holds a "MessageBox" equivalent with a few more bells and whistles.

If I call the ShowDialog(IWin32Owner) method, this works, and the form will display in the centre of my parent form.

Sometimes, however, this form is invoked from a class in my project, and so I don't have access to the form owner. In this situation, I can pass null to the ShowDialog() method, however it appears this doesn't recognize the "Currently Active Window" and display it in the centre. I am assuming because it is in another class library.

Is there any way then to get the currently active form (or at least the screen) the user is working on?

EDIT

Ok this is more to do with the FormStartPosition Enumeration.

If I use CentreScreen this should default to the currently active monitor as per MSDN. However this seems to default to the default monitor if the form is in a class library.

Ok:

This is the code in question: It Fails to set the form to centre screen:

    public static DialogResult ShowYesNoCancel(string message)
    {
        using (frmMessage form = new frmMessage())
        {
            form.Text = @"Input Required";
            form.lblMessage.Text = message;
            form.btnNo.Visible = true;
            form.btnOK.Text = @"Yes";
            form.btnOK.DialogResult = DialogResult.Yes;
            form.StartPosition = FormStartPosition.CenterScreen;
            return form.ShowDialog();
        }
    }

A solution:

    /// <summary>
    /// Overridden to ensure its in the centre of the current screen
    /// </summary>
    /// <returns></returns>
    public new DialogResult ShowDialog()
    {
        Screen current = Screen.FromPoint(MousePosition);
        Rectangle s = current.WorkingArea;
        StartPosition = FormStartPosition.Manual;
        Location = new Point(s.Left + s.Width / 2 - Width / 2, s.Top + s.Height / 2 - Height / 2);
        return base.ShowDialog();
    }
Was it helpful?

Solution

this should default to the currently active monitor

Problem is: which is the "currently active monitor" if you have more than one? If you have two or more then that gets to be a muddled question, a secondary monitor isn't more or less "active" then the primary one, it is equally capable of displaying windows.

The heuristic that Winforms uses is "the monitor that displays the mouse cursor". The underlying call is:

  Screen desktop = Screen.FromPoint(Control.MousePosition);

If you want to emulate the behavior that MessageBox.Show() uses to find an owner then write the code so it finds the currently active window. The underlying winapi call is GetActiveWindow(). Which ShowDialog() already uses so there is probably more going on than meets the eye, like an active window that is not a Winforms window. Which the native MessageBox() winapi function doesn't mind, but ShowDialog() does. Use Spy++ to diagnose this.

OTHER TIPS

You can use Form.ActiveForm:

Gets the currently active form for this application.

However, the fact that your class library is showing this message on its own without already knowing about the UI is probably not a good sign.

Form.ActiveForm will only work if any form of your application has the focus. So if your application is in background, that will be of no help.

Use Application.OpenForms instead. Retrieve the last item in the collection, which represents the last openend form.

Caution with special form properties, like ShowInTaskBar... they might not show up in this collection! Described here: https://stackoverflow.com/a/3751748/2243584

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top