26

MessageBox.Show has forms like MessageBox.Show( ownerWindow, .... ).

What do I gain by assigning a owner window?

Matt Hamilton
  • 200,371
  • 61
  • 386
  • 320
jyoung
  • 5,071
  • 4
  • 30
  • 47

8 Answers8

26

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.

Roger Lipscombe
  • 89,048
  • 55
  • 235
  • 380
Jeffrey L Whitledge
  • 58,241
  • 9
  • 71
  • 99
  • Thanks. So it looks like you only need the use the window owner parameter if you run Messagebox.Show from a different thread from your GUI. – jyoung Oct 12 '08 at 15:49
  • To further clarify: if you need your `MessageBox` to be modal, ensure it is called from an `Invoke()` on the `Form` it needs to be modal to. If you find that you actually need to use `Invoke()`, be sure to also pass in the owner. (So, for example, there is no need to specify `owner` or `Invoke()` when calling `MessageBox.Show()` in a button `Click` event handler). – binki Aug 11 '14 at 17:57
  • I have confirmed that `MessageBox`es spawned from within other threads *do* still need the form to be passed as the first parameter. In fact, that's exactly why the first parameter in numerous `MessageBox.Show()` overloads is the `owner` of the to-be-spawned `MessageBox`. As @binki pointed out, we could have the auto-owner automatically choose the correct form by invoking the desired owner form, but in classes whose primary (and with best practices, only) purpose is housing abstracted code logic, invoking a form seems less desirable than passing it by reference. Plus a param is more concise. – Chad Jan 15 '20 at 21:39
  • Likewise, without passing (or invoking) the `owner` form, your user will be able to still interact with the no-longer-`owner` form instead of being halted by the `MessageBox` in `Form.ShowDialog()` fashion (as opposed to `Form.Show()`). If this is desired functionality for your application, then omit the passing of the form to the `owner` parameter. – Chad Jan 15 '20 at 21:44
3

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.

jop
  • 82,837
  • 10
  • 55
  • 52
Nir
  • 29,306
  • 10
  • 67
  • 103
  • 1
    Can anyone cite an example of a way the owner window can "the user can click something else or even close the owner " while a Message Box is open? – jyoung Oct 12 '08 at 15:27
  • Should read: Can anyone cite an example of a way "the user can click something else or even close the owner " while a Message Box is open? – jyoung Oct 12 '08 at 15:29
  • Actually, you can't close the owner if you don't specify the owner because then there is no owner - but the user can close any application window then. However, if I remember correctly, MessageBox.Show chooses the foreground window as owner if you don't specify one. – OregonGhost Oct 12 '08 at 15:35
3

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 Forms 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.

Community
  • 1
  • 1
binki
  • 7,754
  • 5
  • 64
  • 110
1

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.

jyoung
  • 5,071
  • 4
  • 30
  • 47
  • Does your original form call `Show()` or `ShowDialog()` on its spawned form? I am going to guess `Show()` because when I try to raise the parent of a nested form launched via `ShowDialog()` which owns a `MessageBox`, Windows automatically raises the parent, nested form, and `MessageBox` and blinks the `MessageBox` for me appropriately. – binki Aug 11 '14 at 16:06
1

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().

Felinis
  • 47
  • 3
0

if i'm not wrong this prevents to owner window to Focus() until the messagebox is closed.

Joachim Kerschbaumer
  • 9,695
  • 7
  • 49
  • 84
0

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.

jyoung
  • 5,071
  • 4
  • 30
  • 47
  • Well, no, that's not true; you've discovered what others have already said, which is that the method will assign the owner to be the active window. If you want to be absolutely clear about which window is blocked while the message is active, you should specify it in the method call. – Rob Oct 12 '08 at 15:45
  • Unless you want another window to be the owner. But you're right, I never set the owner for MessageBox.Show in SWF applications and never saw unexpected behaviour. – OregonGhost Oct 12 '08 at 15:45
  • Unless if there is a benefit, "being absolute clear", is a bad thing. It just makes thing slower to read, more error prone, and less maintainable. So as a good programmer, I always look for the benifit. – jyoung Oct 12 '08 at 16:27
  • 1
    I think that there is valid difference between being "absolutely clear" and being "verbose". The former is a *must* to write maintainable code the later one may result in clutter. For this particular case: do you expect your colleges to use reflector to see what is happening? – Christian.K Oct 12 '08 at 17:32
0

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!

Tim Gradwell
  • 2,312
  • 5
  • 24
  • 25