0
 m_pMainWnd->SetForegroundWindow(); 
m_pMainWnd->SetWindowPos(&CWnd::wndTop, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

i used the above lines to bring one of my windows to top. But to my disappointment, nothing is happening. Although using <&CWnd::wndTopMost> is bringong the window to topmost, but no focus on it. VS15, mfc

  • Could it be a restriction of `SetForegroundWindow`, i.e. does the taskbar entry flash instead? – Karsten Koop Jun 30 '16 at 09:49
  • Yes it flashes, but how to overcome? – Devvrat Tomar Jun 30 '16 at 10:03
  • 2
    If the user wants your window to be at the top of the Z order, they will switch to it. As a programmer, you control only the ordering of windows *within* your application, not the ordering of all windows on the desktop. – Cody Gray - on strike Jun 30 '16 at 12:13
  • I think I just might have found a problem. There is a loadframe call. I installed message boxes before it and after it. The message boxes before it were coming in the foreground very well and activated, but those after that call were not coming on top, and were also deactivated and lost focus. Any idea why this might be an issue? Also It was working fine with CFraneWnd, but this issue only occured with CFrameWndEx. – Devvrat Tomar Jul 01 '16 at 06:14

2 Answers2

5

I'm sorry, but what you are asking is not (trivially) possible. The reason your window does not come on top is because your application is not the foreground application (i.e. - the application responsible for the foreground window).

From the manual page:

To use SetWindowPos to bring a window to the top, the process that owns the window must have SetForegroundWindow permission.

Of course, you did that. You did not, however, check its return code. Here is what that man page has to say:

The system restricts which processes can set the foreground window. A process can set the foreground window only if one of the following conditions is true:

  • The process is the foreground process.
  • The process was started by the foreground process.
  • The process received the last input event.
  • There is no foreground process.
  • The process is being debugged.
  • The foreground process is not a Modern Application or the Start Screen.
  • The foreground is not locked (see LockSetForegroundWindow).
  • The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
  • No menus are active.

The sum of these restrictions is that, in all probability, you cannot turn your window into a foreground window, and you cannot bring it to front.

There are ways around that. You can make sure the foreground process calls SetForegroundWindow. Unfortunately, that is not running your code.

The one time I had to do that, I used hooks in order to inject my code into the foreground window's process. This is not a beginner's trick. If you are not up to doing that, then there is no way to do what you are trying to do.

Edited to add: There is a reason Windows tries to stop you from doing what you are trying to do. Stealing the focus from another application creates very poor UI experience for the user. Please reconsider whether you want to do what you are trying to do.

Shachar Shemesh
  • 8,193
  • 6
  • 25
  • 57
  • *"Stealing the focus from another application creates very poor UI experience for the user."* - That's not why Microsoft changed the behavior. They did, because input goes to the foreground window, and stealing the foreground window means stealing your passwords. Besides, the list of restrictions is fairly inaccurate, and has been so for years. If it were correct, then it would be trivially easy to set the foreground window, just by closing all menus. – IInspectable Jul 01 '16 at 01:41
  • You are talking about why MS made it so. You may or may not be right (the same hooks technique will also steal your passwords, after all). I am talking about why you, as a user, *should* not do it. You can, but you still shouldn't. – Shachar Shemesh Jul 01 '16 at 04:19
  • This looks like an example of poorly thought out restrictions making a mess. The argument that this behavior increases security is not currently valid, as easy workarounds are possible. One simple workaround is to set TOPMOST and then NOTTOPMOST. It isn't perfect, as we have the unwanted side effect of potentially flashing in front of a TOPMOST window, so now the restriction has created a mess. This "restriction" also impacts programs that run as administrator, which is silly. – Rick Velde May 21 '20 at 21:20
-2

You should use CWnd::wndTopMost instead of CWnd::wndTop. CWnd::wndTopMost will cause the window to remain topmost even when deactivated.

See documentation: https://msdn.microsoft.com/en-us/library/a1yzfz6d.aspx

An old new thing article on the difference between the two: https://blogs.msdn.microsoft.com/oldnewthing/20051121-10/?p=33263

Jonathan
  • 552
  • 1
  • 4
  • 10
  • TopMost fixes the window on the top, so when any other application is run, the previous window still remains there, which is unacceptable. All I want is that when my app is launched, it should be on the top and opened, but the dialog for registration is coming in background – Devvrat Tomar Jun 30 '16 at 10:05
  • 1
    And another relevant Old New Thing article: [How do I create a topmost window that is never covered by other topmost windows?](https://blogs.msdn.microsoft.com/oldnewthing/20110310-00/?p=11253/) – Cody Gray - on strike Jun 30 '16 at 12:11
  • I guess I misunderstood your actual question. Maybe you could provide more details next time in the original posting to avoid confusion. – Jonathan Jun 30 '16 at 12:57