user500333
user500333

Reputation: 41

When does setting topmost on a window fail to work?

I have a C++ app where I need to create topmost windows. Sometimes it works, but quite often it fails. In one part of the app, I create a background thread to display a topmost information window. After the user closes the window the thread goes away. The first time the app creates the thread and displays the window, the window is topmost. However, all subsequent threads fail to set topmost on their window. I have tried both creating the window with the WS_EX_TOPMOST style and by calling SetWindowPos after the window is created. Neither of these methods works. I looked and was unable to find any references to anyone having a problem where the window could not be set to topmost.

In one test that I ran, I called SetWindowPos and after it returned I checked the window's style and it was not set to topmost even though SetWindowPos returned success. I have also used Spy++ to check the window's style and it confirms that the style is not set.

Upvotes: 4

Views: 4454

Answers (5)

Eugene
Eugene

Reputation: 7258

One way SetWindowPos will silently fail to set WS_EX_TOPMOST is when the process doesn't have permission to SetForegroundWindow at the time window is created or SetWindowPos is called. Which is arguably one of the times you want the window topmost (and arguably one of the times you should not be allowed to).

Rumors are MS closed that loophole since Vista.

The restriction is understandable -- you don't want topmost windows from random processes stealing focus when they have no business too.

A workaround for a reasonable use case when one process indirectly launches a helper process (like would be a case of install initiated in parent process then helper process launched from msiexec) and helper then wants to be topmost or even grab input is to use AllowSetForegroundWindow.

You need to have the right to focus to be able to relinquish it, obviously.

Upvotes: 4

Mike Kwan
Mike Kwan

Reputation: 24447

Why don't you just use SetForegroundWindow(). There's a lot less to go wrong..

Upvotes: 0

Jon Hallin
Jon Hallin

Reputation: 508

No idea if the problem I had was the same as yours, but at least it had the same symptoms. Solved it by moving the this->TopMost = true from InitializeComponent to the Form_Load instead.

Upvotes: 0

Daniel Mošmondor
Daniel Mošmondor

Reputation: 19956

SetWindowPos(_hYourWindow, HWND_TOPMOST, 0, 0, 0, 0,
    SWP_ASYNCWINDOWPOS|SWP_NOSIZE|SWP_SHOWWINDOW|SWP_NOMOVE);

Should work!

Upvotes: 0

selwyn
selwyn

Reputation: 1204

I had a similar problem using Borland C++ Builder. I got this to work by setting the FormStyle to fsStayOnTop after the window was created and displayed. I think that the trick is to do this only after the window is fully displayed.

*visibleForm = new TForm3(Form3);
(*visibleForm)->FormStyle = fsStayOnTop;

Upvotes: 0

Related Questions