【发布时间】:2010-10-06 18:17:17
【问题描述】:
我有一段代码使用 WinXP 的 SetForegroundWindow API 将光标下的窗口置于前台。我一直在为 Vista 测试它,但 API 似乎不再正确地完成这项工作。
AllowSetForeground 没有帮助,我的进程是后台进程。
我可以用什么来完成这项工作?
【问题讨论】:
我有一段代码使用 WinXP 的 SetForegroundWindow API 将光标下的窗口置于前台。我一直在为 Vista 测试它,但 API 似乎不再正确地完成这项工作。
AllowSetForeground 没有帮助,我的进程是后台进程。
我可以用什么来完成这项工作?
【问题讨论】:
试试下面的代码,看看它是否适合你:
SetWindowPos(WndHandle,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE);
SetWindowPos(WndHandle,HWND_NOTOPMOST,0,0,0,0,SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
【讨论】:
只是一个警告:有一个公共 API 可以做到这一点 (SetForegroundWindow),现在它不再将窗口置于前台。
现在窗口只是闪烁。
但这是有原因的。这样做的应用程序从当前窗口“窃取”焦点(通常没有充分的理由),并可能导致各种问题。
因此,在尝试规避操作系统针对此类行为设置的保护措施之前,请确保您不会惹恼您的用户。问问自己:“即使我的应用程序在后台,我真的——真的必须跳到我的用户面前吗?”
【讨论】:
如果使用 MFC,这在 Windows 7 x64 中对我有用:
RECT rc;
m_pMainWnd->GetWindowRect(&rc);
int nBoxWidth = rc.left-rc.right;
int nBoxHeight = rc.bottom-rc.top;
int nBoxTop = rc.top;
int nBoxLeft = rc.left;
SetWindowPos(m_pMainWnd->GetSafeHwnd(), HWND_TOPMOST,
nBoxLeft, nBoxTop, nBoxWidth, nBoxHeight,
SWP_NOMOVE || SWP_NOSIZE);
SetWindowPos(m_pMainWnd->GetSafeHwnd(), HWND_NOTOPMOST,
nBoxLeft, nBoxTop, nBoxWidth, nBoxHeight,
SWP_SHOWWINDOW || SWP_NOMOVE || SWP_NOSIZE);
【讨论】:
将当前线程设置为睡眠对我来说是这样做的,以及之前将其设置为非最顶层:
OS.SetWindowPos(handle, OS.HWND_NOTOPMOST, 0, 0, 0, 0, OS.SWP_NOMOVE | OS.SWP_NOSIZE);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
LOG.error("sleeping thread was interrupted", e);
}
OS.SetWindowPos(handle, OS.HWND_TOPMOST, 0, 0, 0, 0, OS.SWP_NOMOVE | OS.SWP_NOSIZE);
【讨论】:
如果SetForegroundWindow() 失败,您是否尝试过设置窗口WS_EX_TOPMOST,然后在调用SetForegroundWindow() 后立即非最右边?
这可能与人们理所当然地抱怨应用程序在您最意想不到的时候到处出现有关。
【讨论】:
VOID SwitchToThisWindow(HWND hWnd, BOOL fAltTab);
适用于 XP 到 Windows 7 http://msdn.microsoft.com/en-us/library/ms633553.aspx
【讨论】:
使用windows powertoys的tweakui程序来改变焦点的权限状态。
选择“常规”,然后选择“焦点”,然后取消选中允许其他程序获得焦点的复选框。
当每个人的建议似乎都不起作用时,这很有效,(实际上他们都这样做了)。
微软以其无穷的智慧决定,对 setforegrondwindow 等的调用的响应现在将为空。
他们懒得说你仍然可以通过tweakui恢复原状!!!
享受.....
【讨论】: