Search code examples
winapifocusmessagebox

Winapi: window is "sent to back" when using EnableWindow() function


To prevent users from clicking in my main_window when a MessageBox appears I have used:

EnableWindow(main_window,FALSE);

I got a sample MessageBox:

EnableWindow(main_window,FALSE); 
MessageBox(NULL,"some text here","About me",MB_ICONASTERISK);
EnableWindow(main_window,TRUE);

The problem is that when I press "OK" on my MessageBox it closes and my main_window is send to back of all other system windows. Why this is happening? I tried to put:

SetFocus(main_window);
SetActiveWindow(main_window);

after and before : EnableWindow(main_window,TRUE) the result was strange: it worked 50/50. Guess I do it the way it shouldn't be.

Btw. Is there a better solution to BLOCK mouse click's on specific window than:

EnableWindow(main_window,FALSE);

Solution

  • Displaying modal UI requires that the modal child is enabled and the owner is disabled. When the modal child is finished the procedure has to be reversed. The code you posted looks like a straight forward way to implement this.

    Except, it isn't.

    The problem is in between the calls to MessageBox and EnableWindow, code that you did not write. MessageBox returns after the modal child (the message box) has been destroyed. Since this is the window with foreground activiation the window manager then tries to find a new window to activate. There is no owning window, so it starts searching from the top of the Z-order. The first window it finds is yours, but it is still disabled. So the window manager skips it and looks for another window, one that is not disabled. By the time the call to EnableWindow is executed it is too late - the window manager has already concluded that another window should be activated.

    The correct order would be to enable the owner prior to destroying the modal UI.

    This, however, is only necessary if you have a reason to implement modality yourself. The system provides a standard implementation for modal UI. To make use of it pass a handle to the owning window to calls like MessageBox or CreateDialog (*), and the window manager will do all the heavy lifting for you.

    (*): The formal parameter to CreateDialog is unfortunately misnamed as hWndParent. Parent-child and owner-owned relationships are very different (see About Windows).