Is there a built-in shortcut key for selecting the owner of the currently active form?

萝らか妹 提交于 2019-12-06 16:25:12

Setting the Owner of a Form, causes this Form to stay on top of its Owner as a non-modal Window.
If the owned Form has its ShowInTaskbar property set to true, the standard ALT+TAB or WIN+TAB combination of keys used to iterate the opened Windows in the System, brings to front (activates) the next owned Form instead of the Owner.
Which child Form is activated, it depends on the current position of the Form in the Taskbar.

If the ShowInTaskbar property of the children is instead set to false, the Owner Form is activated.
To note that if a child Form can be minimized, some awkward behaviour can be observed: Alt or Control-tabbing, cause the child Forms to appear and disappear in an unpleasant way.

Anyway, the standard combination of CONTROL+F6 keys can be used to move the focus on the opened child Forms (and the Owner Form, in this kind of layout), also bringing them to front if necessary (if the Form is minimized).
Here, overridng ProcessCmdKey, so the combination of keys is intercepted no matter what child control has captured the cursor.

The code here activates a Form pressing both CONTROL+F6 and CONTROL+SHIFT+F6, moving the Focus to each of the opened child Forms and the Owner. It also works when a child Form is minimized (or all the them).

In the Owner Form:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    bool isControlF6 = keyData == (Keys.Control | Keys.F6);
    bool isCtrlShiftF6 = keyData == (Keys.Control | Keys.Shift | Keys.F6);

    if (isControlF6 || isCtrlShiftF6)
    {
        Form frm = isCtrlShiftF6 
                 ? Application.OpenForms.OfType<Form>().LastOrDefault(f => f.Owner == this)
                 : Application.OpenForms.OfType<Form>().FirstOrDefault(f => f.Owner == this);
        if (frm is null) return true;
        frm.WindowState = FormWindowState.Normal;
        frm.Focus();
        return true;
    }
    return base.ProcessCmdKey(ref msg, keyData);
}

In the child Forms:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    bool isControlF6 = keyData == (Keys.Control | Keys.F6);
    bool isCtrlShiftF6 = keyData == (Keys.Control | Keys.Shift | Keys.F6);
    if (isControlF6 || isCtrlShiftF6) {
        int frmNext = 0;
        var formsList = Application.OpenForms.OfType<Form>()
                                   .Where(f => (f.Owner == this.Owner) || (f == this.Owner)).ToList();
        for (int i = 0; i < formsList.Count; i++) {
            if (formsList[i] == this) {
                if (isCtrlShiftF6) { frmNext = i == 0 ? formsList.Count - 1 : i - 1; }
                if (isControlF6) { frmNext = i == formsList.Count - 1 ? 0 : i + 1; }
                formsList[frmNext].WindowState = FormWindowState.Normal;
                formsList[frmNext].Focus();
                return true;
            }
        }
    }
    return base.ProcessCmdKey(ref msg, keyData);
}

Edited answer:

I don't know why but I just couldn't let this go. It seemed there should be an easy solution.

@glopes I believe this is what you are looking for based on your comment.

This code will set the focus back to the parent window just before the child window looses focus. This acts similar to clicking on the window and allows you to Alt-Tab to any window you want.

public class MainForm : Form
{
    Form child1;
    Form child2;

    public MainForm()
    {
        Text = "MainForm";
        child1 = new ChildForm { Text = "Child1", ParentPtr = Handle };
        child2 = new ChildForm { Text = "Child2", ParentPtr = Handle };
        child1.Show(this);
        child2.Show(this);
    }
}

public class ChildForm : Form
{
    [DllImport("user32.dll")]
    public static extern bool SetFocus(IntPtr hWnd);

    private const int WM_KILLFOCUS = 0x0008;

    public IntPtr ParentPtr { get; set; }

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_KILLFOCUS) SetFocus(ParentPtr);

        base.WndProc(ref m);
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!