根据在这里找到的解决方案,我能够遍历Application.Current.Windows列表并在退出系统时关闭它们。然而,可能会有一个对话框(例如OpenFileDialog)打开;不幸的是,这个对话框不在Current.Windows集合中。是否有其他方法来确保所有这样的对话框都被关闭(而不必将它们存储在某个地方的集合中?)
根据在这里找到的解决方案,我能够遍历Application.Current.Windows列表并在退出系统时关闭它们。然而,可能会有一个对话框(例如OpenFileDialog)打开;不幸的是,这个对话框不在Current.Windows集合中。是否有其他方法来确保所有这样的对话框都被关闭(而不必将它们存储在某个地方的集合中?)
要查找所有传统的Win32窗口,您需要枚举线程上的窗口并关闭它们。
一些有用的函数和常量声明:
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hwnd, IntPtr processId);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool EnumThreadWindows(uint dwThreadId, EnumThreadFindWindowDelegate lpfn, IntPtr lParam);
[DllImport("user32", SetLastError = true, CharSet = CharSet.Auto)]
private extern static int GetWindowText(IntPtr hWnd, StringBuilder text, int maxCount);
[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern int SendMessage(int hWnd, int Msg, int wParam, int lParam);
const uint WM_CLOSE = 0x10;
public delegate bool EnumThreadFindWindowDelegate(IntPtr hwnd, IntPtr lParam);
回调函数本身会关闭找到的每个窗口。如果有您不想关闭的窗口,例如顶级窗口,则需要添加自己的条件。下面我已经添加了一些注释代码来获取窗口标题,例如。
static bool EnumThreadCallback(IntPtr hWnd, IntPtr lParam)
{
// If you want to check for a non-closing window by title...
// Get the window's title
//StringBuilder text = new StringBuilder(500);
//GetWindowText(hWnd, text, 500);
SendMessage(hWnd, WM_CLOSE, 0, 0);
// Continue
return true;
}
进行枚举:
uint threadId = Thread.CurrentThread.ManagedThreadId;
EnumThreadWindows(threadId, EnumThreadCallback, IntPtr.Zero);