简体   繁体   中英

C# MDI WinForms child activation

The problem I have is that when one switches from one child form to another a strange thing happens: the form to be shown appears in a strange way as if it has been minimized, restored and then maximized, causing an effect of like several drawing events at the same time.

The problem does not appear (ie, everything works) in these situations:

  • when one switches between forms using CTRL + TAB or CTRL + SHIFT + TAB
  • when child forms are not maximized and one simply changes the order/position of the form

Possibly related; there are a tonne of methods one can called for showing forms, including (and related):

  • child.Focus()
  • child.Show()
  • child.Activate()
  • child.Select()
  • child.BringToFront()

My question is, what exactly should I be calling?

Edit:

In my case, I have the following code that works, but still causes the weird effect I described above:

private void tabForms_MouseClick(object sender, MouseEventArgs e)
{
    // handle middle-mouse-button click (close)
    if (e.Button == System.Windows.Forms.MouseButtons.Middle)
    {
        // See: http://stackoverflow.com/a/745361
        TabPage tab = tabForms.TabPages.Cast<TabPage>().Where((t, i) => tabForms.GetTabRect(i).Contains(e.Location)).FirstOrDefault();
        if (tab != null && tab.Tag != null) (tab.Tag as Form).Close();
    }
    // handle left-mouse-button click (show)
    if ((tabForms.SelectedTab != null) && (tabForms.SelectedTab.Tag != null) && (ActiveMdiChild != tabForms.SelectedTab.Tag))
    {
        (tabForms.SelectedTab.Tag as Form).Select();
        (tabForms.SelectedTab.Tag as Form).Show();
    }
}

PS: Without the .Select() it doesn't work. Although it seems that it still works if I replace .Select() and .Show() with .Focus() .

This might be old now, but for the benefit of anyone else with this issue there's a simple solution to this. You can call the Win32 method LockWindowUpdate , providing the window handle to your form, create and open / maximise your form, then call LockWindowUpdate again and provide an IntPtr.Zero value (as shown below).

try
{
    LockWindowUpdate(this.Handle);

    // Open your form, maximise it etc
}
catch (Exception ex)
{
    // Handle any errors
}
finally
{
    LockWindowUpdate(IntPtr.Zero);
}

LockWindowUpdate disables drawing for whichever window handle you provide it, calling it a second time with a zero IntPtr resumes drawing the window. Only one window can be locked at a time.

You will need two other things; a DLL import, and a using reference for System.Runtime.InteropServices. Here's the DLL import:

[DllImport("user32.dll", EntryPoint = "LockWindowUpdate", SetLastError = true,
        ExactSpelling = true, CharSet = CharSet.Auto,
        CallingConvention = CallingConvention.StdCall)]
public static extern long LockWindowUpdate(IntPtr hWndLock);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM