Win32 ::SetForegroundWindow() not working all the time

10,488

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

Share:
10,488
samitriani
Author by

samitriani

Updated on July 23, 2022

Comments

  • samitriani
    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
    samitriani over 10 years
    The solution that I found is that I put the window on TOPMOST then remove it.
  • Jonathan Potter
    Jonathan Potter over 10 years
    That 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
    samitriani over 10 years
    I should maybe add the activate explicitly. The window is already flashing, but the "Managers" want it to be put on Foreground.
  • c00000fd
    c00000fd over 7 years
    Another hack to make this work is to simulate ALT key press. Here's how.
  • Alexander Høst
    Alexander Høst over 2 years
    It'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.