在SetForegroundWindow之前比較早的時候(比如main函數里)調用一下以下代碼:
- DWORD dwTimeout = -1;
- SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)&dwTimeout, 0);
- if (dwTimeout >= 100) {
- SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
- }
就可以了,后果是如果執行到if里面的語句,會因為user profile的更改回寫和WM_SETTINGCHANGE的廣播而導致這個API調用本身卡兩三秒。
MSDN:http://msdn.microsoft.com/en-us/library/ms633539(v=VS.85).aspx 下面是谷歌翻譯,有些語句不是很流暢。
SetForegroundWindow函數將創建指定的窗口,並激活到前台窗口的線程 。鍵盤輸入窗口,並為用戶更改不同的視覺線索。該系統分配一個優先略高前景的窗口,比它其他線程創建的線程。
語法
BOOL SetForegroundWindow(
HWND HWND );
參數
HWND
[in]應該被激活,並帶到前景的窗口句柄。
返回值
如果窗口被帶到前台,返回值為非零。
如果窗口不帶到前景,返回值是零。
備注
Windows 98/Me的系統限制哪些進程可以設置前台窗口。一個進程可以設置前台窗口,僅當下列條件之一為真 :
這個過程是前台進程。
這個過程是由前台進程的開始。
過程中收到的最后一個輸入事件。
沒有前台進程。
前台進程正在被調試。
前景不被鎖定(見LockSetForegroundWindow)。
前景鎖定超時已過期(看到SPI_GETFOREGROUNDLOCKTIMEOUTSystemParametersInfo)。
Windows 2000/XP的:沒有菜單處於活動狀態。
這一變化,應用程序不能強制一個窗口到前台,而用戶是另一個窗口的工作。相反,前台和后台的Windows激活窗口(見 SetActiveWindow)和調用函數通知用戶 。然而,在Microsoft Windows 98和Windows Millennium Edition(Windows Me)中,如果一個nonforeground線程調用SetForegroundWindow,並通過一個沒有被調用線程創建的窗口的句柄,窗口不閃現在任務欄上。SetForegroundWindow行為相同的,因為它沒有在Windows 95和Microsoft Windows NT 4.0,安裝應用程序時,更改前景色鎖超時值 。這可以從下面的函數調用設置或安裝應用程序:
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
這種方法允許在Windows 98/Windows Me和Windows 2000/Windows XPSetForegroundWindow行為作為Windows 95和Windows NT 4.0相同,分別為所有應用程序,。安裝應用程序,這樣做是使用戶是不會改變的行為感到驚訝的用戶發出警告。在Windows上的Windows 2000和Windows XP,調用失敗,除非調用線程可以改變前台窗口,因此必須從一個安裝或修補應用程序調用。欲了解更多信息,請參閱前景和背景窗口。
一個過程,可以設置前台窗口可以使另一個進程通過調用前台窗口AllowSetForegroundWindow功能。dwProcessId和所指定的過程中失去了到前台窗口設置下一次輸入用戶生成的能力,除非輸入是在這個過程中,或在下一次進程調用AllowSetForegroundWindow,除非指定過程。
前台進程可以禁用調用SetForegroundWindow調用的LockSetForegroundWindow函數。
保證SetForegroundWindow成功
在SetForegroundWindow之前比較早的時候(比如main函數里)調用一下以下代碼:
DWORD dwTimeout = -1;
SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)&dwTimeout, 0);
if (dwTimeout >= 100) {
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
}
HWND hForeWnd = NULL;
HWND hWnd= FindWindow(NULL, "");
DWORD dwForeID;
DWORD dwCurID;
hForeWnd = GetForegroundWindow();
dwCurID = GetCurrentThreadId();
dwForeID = GetWindowThreadProcessId( hForeWnd, NULL );
AttachThreadInput( dwCurID, dwForeID, TRUE);
ShowWindow( hWnd, SW_SHOWNORMAL );
SetWindowPos( hWnd, HWND_TOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE );
SetWindowPos( hWnd, HWND_NOTOPMOST, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE );
SetForegroundWindow( hWnd );
AttachThreadInput( dwCurID, dwForeID, FALSE);
第一段代碼:
后果是如果執行到if里面的語句,會因為user profile的更改回寫和WM_SETTINGCHANGE的廣播而導致這個API調用本身卡兩三秒。
第二段代碼:
設置當前某窗口為當前窗口,有幾個步驟要做:
1.得到窗口句柄FindWindow
2.切換鍵盤輸入焦點AttachThreadInput
3.顯示窗口ShowWindow(有些窗口被最小化/隱藏了)
4.更改窗口的Zorder,SetWindowPos使之最上,為了不影響后續窗口的Zorder,改完之后,再還原
5.最后SetForegroundWindow
想必看到上述代碼就明白了這個函數失敗的原因了吧。