自動ログオフの一部として、子フォームを閉じる必要があります。タイマー スレッドから Application.OpenForms を繰り返すことで、子フォームを閉じることができます。OpenFileDialog がリストされていないため、Application.OpenForms を使用して OpenFileDialog/SaveFileDialog を閉じることができません。
OpenFileDialog と CloseFileDialog を閉じるにはどうすればよいですか?
これには pinvoke が必要です。ダイアログはフォームではなく、ネイティブの Windows ダイアログです。基本的なアプローチは、すべてのトップレベル ウィンドウを列挙し、それらのクラス名が "#32770" (Windows が所有するすべてのダイアログのクラス名) であるかどうかを確認することです。WM_CLOSE メッセージを送信して、ダイアログを強制的に閉じます。
プロジェクトに新しいクラスを追加し、以下に示すコードを貼り付けます。ログアウト タイマーが切れたら、DialogCloser.Execute() を呼び出します。 その後、フォームを閉じます。このコードは、MessageBox、OpenFormDialog、FolderBrowserDialog、PrintDialog、ColorDialog、FontDialog、PageSetupDialog、および 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);
}
1 つのスレッドですべての子フォームを閉じるのではなく、すべての子フォームがサブスクライブできる/サブスクライブする必要があるイベントを発生させます。フォームをレイズすると、今何をすべきかを決定できます。何かをクリーンアップし、状態を保持し、フォームのスコープ内でサーバーにメッセージを送信すると、openfiledialog にアクセスして、それを閉じようとすることができます。
[回避策] 以下に例を示します。
完全に透明なウィンドウ ex を定義する必要があります。"トランス";
ダイアログを表示する必要があるたびに、TRANSP を表示し、TRANSP をパラメーターとして ShowDialog メソッドに渡す必要があります。
アプリケーションがシャットダウンしたら、TRANSP ウィンドウの 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);
}
}
私の答えは、ハンス・パッサントの答えと概念的に似ています。
ただし、別のスレッドから呼び出していたためGetCurrentThreadId()
、tid
パラメーターとして使用しEnumThreadWindows
ても機能しませんでした。それを行っている場合は、プロセスのスレッド ID を列挙し、必要なウィンドウが見つかるまでそれぞれを試してください。
ProcessThreadCollection currentThreads = Process.GetCurrentProcess().Threads;
foreach (ProcessThread thread in currentThreads) {
CloseAllDialogs(thread.Id);
}
ShowDialog
または、開くために実行するスレッド ID を保存しますCommonDialog
。
threadId = GetCurrentThreadId();
threadIds.Add(threadId);
result = dialog.ShowDialog()
threadIds.Remove(threadId);
その後:
foreach (int threadId in threadIds) {
CloseAllDialogs(threadId);
}
次CloseAllDialogs
のようになります。
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);