Win32 ::SetForegroundWindow() not working all the time
Solution 1
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 foreground process is being debugged.
- The foreground is not locked (see LockSetForegroundWindow).
- The foreground lock time-out has expired (see SPI_GETFOREGROUNDLOCKTIMEOUT in SystemParametersInfo).
- No menus are active.
See the SetForegroundWindow()
docs for more details.
Solution 2
In the official document of Win32 API, there are remarks:
Remarks 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.
But there is a trick to force a window to foreground:
The trick is to make windows ‘think’ that our process and the target window (hwnd) are related by attaching the threads (using AttachThreadInput API) and using an alternative API: BringWindowToTop.
void CommonHelpers::forceForegroundWindow(HWND hwnd) {
DWORD windowThreadProcessId = GetWindowThreadProcessId(GetForegroundWindow(),LPDWORD(0));
DWORD currentThreadId = GetCurrentThreadId();
DWORD CONST_SW_SHOW = 5;
AttachThreadInput(windowThreadProcessId, currentThreadId, true);
BringWindowToTop(hwnd);
ShowWindow(hwnd, CONST_SW_SHOW);
AttachThreadInput(windowThreadProcessId,currentThreadId, false);
}
The original answer is here
P.S: I also dont think you should bring your message app to top if some message is coming up, but still ... this is the solution that working for my Qt App on Windows 10
samitriani
Updated on July 23, 2022Comments
-
samitriani almost 2 years
I'm working on a messenging tool. The messaging window is part of a whole application. I need the window to go to the front when there are some messages coming. I'am using this code :
if( m_hwnd == NULL || !::IsWindow(m_hwnd) ) return E_UNEXPECTED; if(::IsIconic(m_hwnd)) { ::ShowWindowAsync( m_hwnd, SW_RESTORE ); } ::SetWindowPos(m_hwnd, HWND_TOP, 0, 0, 0, 0, SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); ::SetForegroundWindow(m_hwnd); if( pvbProcessed != NULL ) *pvbProcessed = VARIANT_TRUE; return S_OK;
I even tried to do a TOPMOST but still in some cases it does not work. I also Tried a ::BringToFront().
Anyone can help or give an explanation on why it doen not work ? Is it a known microsoft limitation.
-
samitriani over 10 yearsThe solution that I found is that I put the window on TOPMOST then remove it.
-
Jonathan Potter over 10 yearsThat will bring it to the top but not necessarily make it active (i.e. it won't be the foreground window), but if that's all you want then great.
-
samitriani over 10 yearsI should maybe add the activate explicitly. The window is already flashing, but the "Managers" want it to be put on Foreground.
-
c00000fd over 7 yearsAnother hack to make this work is to simulate
ALT
key press. Here's how. -
Alexander Høst over 2 yearsIt's so important to notice point 5 on the list, which can lead the developer to believe that the implementation is working because it's working in debug. This does not mean it will necessarily work in release.