I am working on trying to close a specific MessageBox if it shows up based on the caption and text. I have it working when the MessageBox doesn't have an icon.
IntPtr handle = FindWindowByCaption(IntPtr.Zero, "Caption");
if (handle == IntPtr.Zero)
return;
//Get the Text window handle
IntPtr txtHandle = FindWindowEx(handle, IntPtr.Zero, "Static", null);
int len = GetWindowTextLength(txtHandle);
//Get the text
StringBuilder sb = new StringBuilder(len + 1);
GetWindowText(txtHandle, sb, len + 1);
//close the messagebox
if (sb.ToString() == "Original message")
{
SendMessage(new HandleRef(null, handle), WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
}
The above code works just fine when the MessageBox is shown without an icon like the following.
MessageBox.Show("Original message", "Caption");
However, if it includes an icon (from MessageBoxIcon) like the following, it doesn't work; GetWindowTextLength returns 0 and nothing happens.
MessageBox.Show("Original message", "Caption", MessageBoxButtons.OK, MessageBoxIcon.Information);
My best guess is that the 3rd and/or 4th paramters of FindWindowEx need to change but I'm not sure what to pass instead. Or maybe the 2nd parameter needs to change to skip the icon? I'm not really sure.
It appears that when the MessageBox has an icon,
FindWindowExreturns the text of the first child (which is the icon in this case) hence, the zero length. Now, with the help of this answer, I got the idea to iterate the children until finding one with a text. This should work:Obviously, you could adjust it to fit your particular situation (e.g., keep iterating until you find the actual text you're looking for) although I think the child with the text will probably always be the second one: