I have 2 forms that are visible. Is it possible to detect if a message box is visible/being displayed on from one of the forms on the other?
+2
A:
The simplest way to do this would be to make your own wrapper around MessageBox.Show
that tracks calls in a Shared
property, then call it exclusively instead of MessageBox.Show
and MsgBox
.
SLaks
2010-02-25 19:08:54
I wonder why System.Windows.Forms.MessageBox has a private constructor. It would be much easier if you could just inherit from the base implementation and change the hide/show methods.
Nathan Taylor
2010-02-25 19:20:01
It's a `Shared` class. That wouldn't be possible.
SLaks
2010-02-25 19:23:02
Good point. That makes sense.
Nathan Taylor
2010-02-25 19:36:34
+2
A:
It is possible, but requires a fairly heavy serving of P/Invoke. The trick is to enumerate the windows owned by the UI thread and check if one of them is a Windows dialog window. This code will do the trick. I can't guarantee a 100% accuracy, there might be another unmanaged dialog in an app that resembles the message box template.
using System;
using System.Text;
using System.Runtime.InteropServices;
static class MessageBoxFinder {
public static bool IsPresent() {
// Enumerate windows to find the message box
EnumThreadWndProc callback = new EnumThreadWndProc(checkWindow);
return false == EnumThreadWindows(GetCurrentThreadId(), callback, IntPtr.Zero);
}
private static bool checkWindow(IntPtr hWnd, IntPtr lp) {
// Checks if <hWnd> is a dialog
StringBuilder sb = new StringBuilder(260);
GetClassName(hWnd, sb, sb.Capacity);
if (sb.ToString() != "#32770") return true;
// Got a dialog, check if the the STATIC control is present
IntPtr hText = GetDlgItem(hWnd, 0xffff);
return hText == IntPtr.Zero;
}
// 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 GetDlgItem(IntPtr hWnd, int item);
}
Hans Passant
2010-02-25 19:22:49
A:
I figured it out, the easiest answer is using this and looking for the title of the message box:
<System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
End Function
DaRkMuCk
2010-02-25 20:38:32