我正在研究一个消息工具。消息传递窗口是整个应用程序的一部分。当有一些消息传来时,我需要窗口转到前面。我正在使用这段代码:
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()。
任何人都可以帮助或解释为什么它不起作用?这是一个已知的微软限制。
答案 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应用程序的解决方案