强行关闭从代码中所有打开弹出窗口
我要导致所有打开弹出式窗口(与StaysOpen == false)来从代码中关闭。基本上我想模拟用户点击鼠标(这将关闭弹出窗口)的代码。
I want to cause all open popups (with StaysOpen == false) to close from code. Basically I want to simulate the user clicking the mouse (which would close the popups) from code.
我不需要实际模拟点击,我需要的只是产生的行为。我想过只是要通过视觉树找弹出和关闭每一个,但是这似乎并不像最干净的方法。
I don't need to actually simulate the click, I just need the resulting behavior. I've thought about just going through the visual tree looking for popups and closing each one, but that doesn't seem like the cleanest approach.
提前任何感谢帮助或意见。
Thanks in advance for any help or opinions.
一个WPF弹出实际上创建了一个新的窗口(一个Win32窗口,而不是一个WPF 窗口
实例)。所以你不能找到它的 Application.Windows
集合中,但你也许可以找到使用的Win32 API一样的 EnumChildWindows
。
A WPF popup actually creates a new window (a Win32 window, not a WPF Window
instance). So you can't find it in the Application.Windows
collection, but you can probably find it using a Win32 API like EnumChildWindows
.
一旦你的手柄,可以检索相关 HwndSource
。我觉得 RootVisual
的 HwndSource
是弹出
( 。没有检查,你可能在可视化树看起来更深)
Once you have the handle, you can retrieve the associated HwndSource
. I think the RootVisual
of the HwndSource
is the Popup
(didn't check, you might have to look deeper in the visual tree).
因此,代码应该类似这样(没有经过充分测试):
So the code should be similar to this (completely untested):
public static class PopupCloser
{
public static void CloseAllPopups()
{
foreach(Window window in Application.Current.Windows)
{
CloseAllPopups(window);
}
}
public static void CloseAllPopups(Window window)
{
IntPtr handle = new WindowInteropHelper(window).Handle;
EnumChildWindows(handle, ClosePopup, IntPtr.Zero);
}
private static bool ClosePopup(IntPtr hwnd, IntPtr lParam)
{
HwndSource source = HwndSource.FromHwnd(hwnd);
if (source != null)
{
Popup popup = source.RootVisual as Popup;
if (popup != null)
{
popup.IsOpen = false;
}
}
return true; // to continue enumeration
}
private delegate bool EnumWindowsProc(IntPtr hwnd, IntPtr lParam);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
}