0

When using the Focus() method, the targeted form acquire focus but is also brought in front of the other forms.

Is there a way to avoid this z-order modification ?

Here is a short example :

class MyForm : Form
{
    static void Main(string[] args)
    {
        MyForm f1 = new MyForm()
        {
            Text = "f1"
        };
        f1.Show();

        MyForm f2 = new MyForm()
        {
            Text = "f2"
        };
        f2.Show();

        Button b1 = new Button();
        b1.Click += (sender, e) => f2.Focus();
        f1.Controls.Add(b1);

        Button b2 = new Button();
        b2.Click += (sender, e) => f1.Focus();
        f2.Controls.Add(b2);

        Application.Run(f1);
    }
}

When clicking the button in f1, f2 will gain focus but will also come in front of f1 (which is the thing I'd like to avoid).

TaW
  • 53,122
  • 8
  • 69
  • 111
A. Jacquet
  • 51
  • 9
  • Will setting f1.TopMost = true; work for you? – Troy Mac1ure Dec 15 '16 at 08:07
  • You tagged `BringToFront`. This and/or `SendToBack` probably could order the forms as needed, but the initial change most likely can't be avoided, as it usually is wanted. – TaW Dec 15 '16 at 08:30
  • @TroyMac1ure : using TopMost will not work since `f2` should be able to get in front of `f1` in some cases (for example if `f2` is clicked). – A. Jacquet Dec 15 '16 at 09:16
  • @TaW : Problem is that `BringToFront` also give focus to the targeted form. Using `SendToBack` like this `b1.Click += (sender, e) => { f2.Focus(); f2.SendToBack(); };` works only if their is no other window opened in the desktop. – A. Jacquet Dec 15 '16 at 09:23
  • 1
    This all sounds like a x-y-problem. The form with focus certainly must not be covered or else the word focus wouldn't mean anything.. – TaW Dec 15 '16 at 10:40

1 Answers1

0

Not really sure it's the best way to do it, but I ended up using the owner property :

class MyForm : Form
{
    public const int WM_NCLBUTTONDOWN = 0x00A1;

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case WM_NCLBUTTONDOWN:
                TakeFocus();
                base.WndProc(ref m);
                break;

            default:
                base.WndProc(ref m);
                break;
        }
    }

    private void TakeFocus()
    {
        if (Owner == null && OwnedForms.Length > 0)
        {
            Form tmp = OwnedForms[0];
            tmp.Owner = null;
            Owner = tmp;
        }
        BringToFront();
    }

    static void Main(string[] args)
    {
        MyForm f1 = new MyForm()
        {
            Text = "f1",
        };
        f1.Show();

        MyForm f2 = new MyForm()
        {
            Text = "f2",
        };
        f2.Owner = f1;
        f2.Show();

        Button b1 = new Button();
        b1.Click += (sender, e) =>
        {
            f1.TakeFocus();
        };
        f1.Controls.Add(b1);

        Button b2 = new Button();
        b2.Click += (sender, e) =>
        {
            f2.TakeFocus();
        };
        f2.Controls.Add(b2);

        Application.Run(f1);
    }
}

In this example, a window gain focus without going in front of the other window when clicking on it's client area. If you click on the non-client area (titlebar and borders) or the button the form gain focus and is brought in front.

A. Jacquet
  • 51
  • 9