我有一堆表单,一些是从主线程创建的,另一些是从其他线程创建的。
假设我在屏幕上打开所有这些表单。如果我在其上打开另一个窗口(例如谷歌浏览器),然后在窗口栏中单击我的应用程序,只有从我的主线程创建的表单被带到前面。我需要将所有这些都放在前面,但不要让他们专注。
这似乎是我发现的一个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顺序都已更改,或者可以保证我这样做)。
我感谢任何帮助!谢谢!