[ACCEPTED]-Closing OpenFileDialog/SaveFileDialog-winforms
This is going to require pinvoke, the dialogs 11 are not Forms but native Windows dialogs. The 10 basic approach is to enumerate all toplevel 9 windows and check if their class name is 8 "#32770", the class name for all dialogs 7 owned by Windows. And force the dialog 6 to close by sending the WM_CLOSE message.
Add 5 a new class to your project and paste the 4 code shown below. Call DialogCloser.Execute() when 3 the logout timer expires. Then close the forms. The 2 code will work for MessageBox, OpenFormDialog, FolderBrowserDialog, PrintDialog, ColorDialog, FontDialog, PageSetupDialog 1 and SaveFileDialog.
using System;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
static class DialogCloser {
public static void Execute() {
// Enumerate windows to find dialogs
EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow);
EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero);
GC.KeepAlive(callback);
}
private static bool checkWindow(IntPtr hWnd, IntPtr lp) {
// Checks if <hWnd> is a Windows dialog
StringBuilder sb = new StringBuilder(260);
GetClassName(hWnd, sb, sb.Capacity);
if (sb.ToString() == "#32770") {
// Close it by sending WM_CLOSE to the window
SendMessage(hWnd, 0x0010, IntPtr.Zero, IntPtr.Zero);
}
return true;
}
// P/Invoke declarations
private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp);
[DllImport("user32.dll")]
private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp);
[DllImport("kernel32.dll")]
private static extern int GetCurrentThreadId();
[DllImport("user32.dll")]
private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen);
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
}
i would not close all child forms in one 7 thread but rather raise an event that every 6 child form can/must subscribe to. on raise 5 your forms can decide what to do now. clean 4 up something, persist state, send a message 3 to the server in the scope of your form 2 you can access the openfiledialog and try 1 to close that.
[workaround] here is example:
You should 6 define fully transparent window ex. "TRANSP";
Every 5 time you need to show dialog, you need to 4 show TRANSP and pass TRANSP as a parameter 3 to ShowDialog method.
When the application 2 shuts down - call Close() Method of TRANSP 1 window. Child dialogs will close.
public partial class MainWindow : Window
{
OpenFileDialog dlg;
TranspWnd transpWnd;
public MainWindow()
{
InitializeComponent();
Timer t = new Timer();
t.Interval = 2500;
t.Elapsed += new ElapsedEventHandler(t_Elapsed);
t.Start();
}
void t_Elapsed(object sender, ElapsedEventArgs e)
{
Dispatcher.BeginInvoke(new Action(() =>
{
transpWnd.Close();
}), null);
}
private void button1_Click(object sender, RoutedEventArgs e)
{
transpWnd = new TranspWnd();
transpWnd.Visibility = System.Windows.Visibility.Hidden; //doesn't works right
transpWnd.Show();
dlg = new OpenFileDialog();
dlg.ShowDialog(transpWnd);
}
}
My answer is conceptually similar to Hans Passant's answer.
However, using 7 GetCurrentThreadId()
as the tid
parameter to EnumThreadWindows
did not work for 6 me since I was calling it from another thread. If 5 you're doing that, then either enumerate 4 the process' thread IDs and try each one 3 until you find the windows you need:
ProcessThreadCollection currentThreads = Process.GetCurrentProcess().Threads;
foreach (ProcessThread thread in currentThreads) {
CloseAllDialogs(thread.Id);
}
Or save 2 off the thread IDs that do the ShowDialog
to open 1 the CommonDialog
:
threadId = GetCurrentThreadId();
threadIds.Add(threadId);
result = dialog.ShowDialog()
threadIds.Remove(threadId);
and then:
foreach (int threadId in threadIds) {
CloseAllDialogs(threadId);
}
Where CloseAllDialogs
looks like:
public void CloseAllDialogs(int threadId) {
EnumThreadWndProc callback = new EnumThreadWndProc(checkIfHWNDPointsToWindowsDialog);
EnumThreadWindows(threadId, callback, IntPtr.Zero);
GC.KeepAlive(callback);
}
private bool checkIfHWNDPointsToWindowsDialog(IntPtr hWnd, IntPtr lp) {
StringBuilder sb = new StringBuilder(260);
GetClassName(hWnd, sb, sb.Capacity);
if (sb.ToString() == "#32770") {
SendMessage(hWnd, 0x0010, IntPtr.Zero, IntPtr.Zero);
}
return true;
}
private delegate bool EnumThreadWndProc(IntPtr hWnd, IntPtr lp);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool EnumThreadWindows(int tid, EnumThreadWndProc callback, IntPtr lp);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern int GetCurrentThreadId();
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetClassName(IntPtr hWnd, StringBuilder buffer, int buflen);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.