Win32 :: SetForegroundWindow()不能一直工作

时间:2013-10-02 11:58:37

标签: c++ windows visual-studio-2010 winapi

我正在研究一个消息工具。消息传递窗口是整个应用程序的一部分。当有一些消息传来时,我需要窗口转到前面。我正在使用这段代码:

    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;

我甚至试图做一个TOPMOST,但在某些情况下它仍然无效。 我还尝试了:: BringToFront()。

任何人都可以帮助或解释为什么它不起作用?这是一个已知的微软限制。

2 个答案:

答案 0 :(得分:7)

  

系统限制哪些进程可以设置前景窗口。一个   只有在以下情况之一时,进程才能设置前台窗口   条件是真的:

     
      
  • 该过程是前台过程。
  •   
  • 该过程由前台进程启动。
  •   
  • 该过程收到了最后一个输入事件。
  •   
  • 没有前台进程。
  •   
  • 正在调试前台进程。
  •   
  • 未锁定前景(请参阅LockSetForegroundWindow)。
  •   
  • 前台锁定超时已过期(请参阅SystemParametersInfo中的SPI_GETFOREGROUNDLOCKTIMEOUT)。
  •   
  • 没有菜单处于活动状态。
  •   

有关详细信息,请参阅SetForegroundWindow() docs

答案 1 :(得分:4)

在Win32 API的正式文档中,有以下说明:

备注系统限制哪些进程可以设置前台 窗口。仅当以下情况之一时,进程才能设置前景窗口: 满足以下条件:

  • 该过程是前台过程。
  • 该过程由前台过程启动。
  • 该进程收到了最后一个输入事件。
  • 没有前台进程。
  • 该进程正在调试中。
  • 前台进程不是现代应用程序或“开始”屏幕。
  • 前景未锁定(请参见LockSetForegroundWindow)。
  • 前台锁定超时已到期(请参阅SystemParametersInfo中的SPI_GETFOREGROUNDLOCKTIMEOUT)。
  • 没有菜单处于活动状态。

但是有一个技巧可以将窗口强制显示为前景:

技巧是通过附加线程(使用AttachThreadInput API)并使用其他API:BringWindowToTop,使窗口“思考”我们的进程和目标窗口(hwnd)的关联。

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);
}

原始答案是here

P.S:我也认为如果出现某些消息,您不应该将消息应用程序置于顶部,但是...这仍然是在Windows 10上适用于我的Qt应用程序的解决方案