MessageBox.Show has forms like MessageBox.Show( ownerWindow, .... ).
What do I gain by assigning a owner window?
MessageBox.Show has forms like MessageBox.Show( ownerWindow, .... ).
What do I gain by assigning a owner window?
A message box is a modal form, which means that its parent window is disabled until the message box is dismissed.
If a Show() overload is called that does not take an owner identifier, then a parent form is usually chosen automatically. I can't find anything in the documentation that describes how that form is chosen, but my experience is that if the message box is displayed inside the GUI thread (i.e., the main thread, or message pump thread), then the active window for that thread is chosen as the parent.
Other threads may create message boxes with no parent form. This could be a bad situation, because it could sit behind the active window, and the user will not even know it is there until they close the program. To avoid this, you could pass the handle of the application's main window to the Show method, which will disable that window for the duration of the message box.
ADDED: I've been thinking about this and now I'm not so sure. The snippet from reflector that you gave below makes me think that maybe the thread doesn't matter. (I did say that I couldn't find anything in the documentation!)
I'd have to go back and look at the code to make sure, but I think the message boxes that I used to lose behind the main form may have actually been custom message box forms, in which case my experience is faulty, and you never ever have to supply a parent form parameter.
Sorry for the confusion.
My recommendation now is to never supply this parameter unless you need something other than the active window to be the main form.
Setting the owner causes the owner to be disabled while the message box is open.
If you don't set the owner then the user can click something else or even close the owner while the message box is open, then when the message box closes and the code after the call to MessageBox.Show runs your program can be in an unknown state - or if the owner was closed you are now running code inside a window that no longer exists and any calls to methods of WinForms or WPF (or for that matter also WinAPI and any other framework) are likely to cause a crash.
Based on testing and this other answer, .net will automatically choose the currently focused window in the same thread as your MessageBox.Show()
call. To get the correct behavior, you must ensure that you display the MessageBox
from the same thread as this window and specify the window the MessageBox
is logically associated with as its owner
. A MessageBox
only modal-ly blocks input to other Form
s on the thread from which it is launched. This is probably related to how MessageBox
makes itself modal (maybe it intercepts messages aimed at the current thread and only allows some messages through to windows other than itself?). The effect of modal-ly blocking input is that the user will be unable to focus these windows or any controls inside of them and attempting to do so produces the "Ding" sound. Also, if the owner is not specified, the MessageBox
will automatically select the active window on the current thread. If the currently active window is from a different thread (or different application!), the MessageBox
will have no owner. That means it gets its own Task Bar entry: it behaves as its own distinct window. The user can raise other windows in your application (even if the user cannot interact with them). You can get the situation where your program stops responding to user input with the user confused because the user somehow raised your application's main window after the dialog was displayed. If the owner is properly set, however, trying to raise your main window will cause the MessageBox
to be raised and blinked.
To make this all work nicely with child windows, ensure that each child window has its Owner
property set. This will happen automatically if you call ShowDialog()
(which makes your custom Form
modal (and do pass its owner
parameter in the same cases where you would pass owner
to MessageBox.Show()
)).
Now, most winforms coding consists of writing code directly into event handlers inside a Form
subclass. When writing winforms event handlers, you can assume many things. First, you should never have a call to this.Invoke()
as a top level statement in a GUI event handler because such handlers are always run on the same thread as the Form
subclass was created on. Secondly, for many (but not all) of these handlers, you can assume that the Form
has focus (and would be thus automatically chosen by MessageBox.Show()
as its owner). For example, when writing code inside of a button's Click event handler (possibly called button1_Click
), you can safely assume that the form is focused (because calling PerformClick()
on another form's Button
is bad practice). However, a Timer.Tick
may happen even when your form is not focused. So, in the case of Timer.Tick
, there is no need to Invoke()
(just like any other winforms event handler) but there is a need to specify owner
. This latter case is trickier to notice because the developer must have their application unfocused to notice that a dialog displayed in this case behaves slightly differently from when their application is focused. So, specify owner
whenever you need to use Invoke()
or if it is possible for the event to be triggered when the window is not focused. This guideline applies when calling MessageBox.Show()
and Form.ShowDialog()
.
Most of what I discuss here is the result of messing around while reading the other answers.
It turns out that window ownership is not transitive. In the case where you have form, spawning a form, spawning a MessageBox, The MessageBox.Show needs to use the ownerWindow parameter. The original form should be set as the owner window of the MessageBox.
Calling MessageBox.Show(frmMain,"a message","a title")
adds the form TextDialog
to the application's Application.OpenForms()
forms collection, along-side the frmMain Main form itself. It remains after you close the Messagebox.
I just discovered 14 of these when I called btnOK_Click()
and set a breakpoint.
When I called frmMain.Close()
to close the main form, nothing happened. frmMain will not close until all 14 of the Application.OpenForms are closed as well or else you must call Application.Exit()
.
if i'm not wrong this prevents to owner window to Focus() until the messagebox is closed.
Using Net Reflector, I just found this code in Messagebox.Show:
else if (owner == IntPtr.Zero)
owner = UnsafeNativeMethods.GetActiveWindow();
So if you do not nested ownership ( window--(owns)-->window--(owns)->messageBox), leaving out the ownerWindow sets the owner you would normally choose.
The documentation seems to imply that the only purpose of the owner parameter is if you specify MB_HELP, the message box knows which window it should send the WM_HELP message to.
http://msdn.microsoft.com/en-us/library/ms645505%28VS.85%29.aspx
Oh, just realised the OP was about .net - I gave an answer about winapi - sorry!