来自其他线程的表单不会被带到前面

时间:2014-03-24 10:59:15

标签: c# multithreading winforms user32 wndproc

我有一堆表单,一些是从主线程创建的,另一些是从其他线程创建的。

假设我在屏幕上打开所有这些表单。如果我在其上打开另一个窗口(例如谷歌浏览器),然后在窗口栏中单击我的应用程序,只有从我的主线程创建的表单被带到前面。我需要将所有这些都放在前面,但不要让他们专注。

这似乎是我发现的一个Windows错误。

以下解决方法可以将窗口置于前面:

private const int WM_WINDOWPOSCHANGING = 0x0046;

protected override void WndProc(ref Message m)
{
    switch (m.Msg)
    {
         case WM_WINDOWPOSCHANGING:
              if (Control.FromHandle(m.LParam) == null)
              {
                  var openForms = this.GetOpenForms();
                  foreach (var openForm in openForms)
                  {
                      ShowInactive(openForm, true);
                  }
              }
              break;
      }

      base.WndProc(ref m);
}

其中 GetOpenForms()返回应用程序打开的表单列表。 ShowInactive(...)功能定义如下:

private static void ShowInactive(Form frm, bool topMost)
{
     if (frm.InvokeRequired)
     {
         frm.Invoke(new MethodInvoker(() => ShowInactive(frm, topMost)));
         return;
     }

     const int SWP_SHOWWINDOW = 0x0040;
     const int SWP_NOSIZE = 0x0001;
     const int SWP_NOMOVE = 0x0002;

     User32.SetWindowPos(
         frm.Handle.ToInt32(),
         topMost ? User32.HWND_TOPMOST : User32.HWND_NOTOPMOST,
         0,
         0,
         0,
         0,
         User32.SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
    }

我已经测试了这种方法,如果其他窗户位于我的上方,似乎工作正常。但是,在将窗口放在顶部之后,我应该将TopMost属性覆盖为false,这样它们就不会永远保持这样。

基本上,我需要为列表中的每个表单调用ShowInactive(frm, false)。问题是在何时何地(无法找到任何事件告诉我所有表格的z顺序都已更改,或者可以保证我这样做)。

我感谢任何帮助!谢谢!

0 个答案:

没有答案