The explanation
The usual rule in MFC is that OnXxx
functions are called in response to similarly named window messages, e.g. WM_Xxx
. So OnShowWindow
would be called in response to WM_SHOWWINDOW
.
And according to the documentation, WM_SHOWWINDOW
is
Sent to a window when the window is about to be hidden or shown.
That means it is sent before the window is actually shown. So when you set the focus to the parent window inside of the OnShowWindow
function, nothing actually happens because the parent window already has the focus. Then, after OnShowWindow
finishes running, the child window is displayed and demands the focus. It is as if you never made any attempt to change the focus.
By contrast, OnSetFocus
, which corresponds to WM_SETFOCUS
, is not called until after the window has gained the focus. So when you reassign the focus here, it works because the child window doesn't steal the focus back.
The better idea
That explains the behavior you are seeing, and as you know, things work fine when you adjust the focus in OnSetFocus
. But this really isn't the best way of solving the problem.
Manually changing the focus when a window gets and/or loses the focus is approaching the problem the wrong way around, and generally error-prone. You'll get all kinds of focus-related bugs that are difficult to debug. You are better off looking for ways to prevent the focus from changing when you don't want it to.
It sounds to me like you want to prevent the child window from getting the focus when it is created. And there is a way to do precisely that.
When you display the child window, presumably by calling the ShowWindow
function or its moral equivalent in MFC, you should pass the SW_SHOWNA
flag. That causes the window to be shown without activating it (i.e., granting it the focus).