SetForegroundWindow的問題 |
答題得分者是:wameng
|
P.D.
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:603 回覆:4038 積分:3874 註冊:2006-10-31 發送簡訊給我 |
請問各位:
我設計兩支程式,一支在Terminal Server運行,一支在Client端運作(見圖二),當中有利用Tcp溝通連繫,而我在TS下(TS是透過遠端桌面方式進入,且是全螢幕)有一個BUTTON[咪叫前台](見圖一),可以利用SetForegroundWindow等API Function 將 Client端的主程式(見圖三),在遠端桌面模式下叫出來到前台,而且主程式視窗也可以做任何focus及點選,但有時候會遇到一個狀況,就是當我在主程式下要切回TS下,於是我在主程式點選右上角的最小化按鈕,這個時候卻沒有作動,但回頭點主程式視窗內各種按鋌或Checkbox都有反應,唯讀最小化不行,結果我必須先縮小遠端桌面,回到Client端,然後在工作列上(見圖二)的主程式(見圖二右邊那塊)以滑鼠右鍵點主程式,然後選擇[還原],會看到有一個視窗外框還原到主程式位置,這個時候再點選最小化才會有反應,為什麼會有如此狀況,我測試結果並不是每次都會,做10次[呼叫前台]button動作,約有2-3次會發生,不知有沒有遇過的前輩佑道如何解決? 謝謝! ![]() |
wameng
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:31 回覆:1336 積分:1188 註冊:2004-09-16 發送簡訊給我 |
|
P.D.
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:603 回覆:4038 積分:3874 註冊:2006-10-31 發送簡訊給我 |
本來我的程式是這樣做的
<textarea class="delphi" rows="10" cols="60" name="code">SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @timeout, 0); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(0),SPIF_SENDCHANGE); BringWindowToTop(hwnd); SetForegroundWindow(hWnd); ShowWindow(hwnd,SW_SHOWNORMAL); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(timeout), SPIF_SENDCHANGE); </textarea> 如果把 SetForegroundWindow(hWnd); ShowWindow(hwnd,SW_SHOWNORMAL); 這兩段改為 if IsIconic(hwnd) then ShowWindow(hwnd,SW_RESTORE) else SetForegroundWindow(hWnd); 則會發生,如果Client端程式在最小化時,在遠端桌面上並沒有辦法真正被Show到前台 所以問題還是沒有解決! ===================引 用 wameng 文 章=================== 應該是這樣吧!由於你直接調用更改視窗狀態的API。 導致 Dlephi 與 Window 並不同步。 應該在 SetForeGroundWindow 之前做IsIconic的判斷 if IsIconic(XX) then Restore else SetForegroundwindow 試試。 |
wameng
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:31 回覆:1336 積分:1188 註冊:2004-09-16 發送簡訊給我 |
|
P.D.
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:603 回覆:4038 積分:3874 註冊:2006-10-31 發送簡訊給我 |
呵呵呵,wameng版主講的方式我都試過了,
不管是 if IsIconic(hwnd) then ShowWindow(hwnd,SW_RESTORE); SetForegroundWindow(hWnd); 或是 if IsIconic(hwnd) then ShowWindow(hwnd,SW_RESTORE); SetForegroundWindow(hWnd); ShowWindow(hwnd,SW_SHOWNORMAL); // 強制視窗顯示出來, 因為 RESTORE 方式在當程式原本就是最小化,透過SetForegroundWindow前置到晝面後,仍然是保持最小化,並不會將視窗SHOW到原來的大小,必須使用SHOWNORMAL 但仍然會造成最小化無反應,除非我自己在工作列手動選擇[還原],這就是我最困擾的! 以上我不是只有測這兩種,大約十來種搭配組合都嘗試過,均告失敗 ===================引 用 wameng 文 章=================== 很久以前遇到過,也忘記詳細是怎麼弄。 多試試。 Restore 後,在SetForegroundWindow 使 Window Active。 ?if IsIconic(hwnd) then ShowWindow(hwnd,SW_RESTORE); ?SetForegroundWindow(hWnd); |
wameng
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:31 回覆:1336 積分:1188 註冊:2004-09-16 發送簡訊給我 |
if IsIconic(Handle) then ShowWindow(Handle, SW_RESTORE);
SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @timeout, 0); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(0),SPIF_SENDCHANGE); BringWindowToTop(Handle); SetForegroundWindow(Handle); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(timeout), SPIF_SENDCHANGE); |
wameng
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:31 回覆:1336 積分:1188 註冊:2004-09-16 發送簡訊給我 |
或者用
function ForceForegroundWindow(hwnd: THandle): Boolean; const SPI_GETFOREGROUNDLOCKTIMEOUT = $2000; SPI_SETFOREGROUNDLOCKTIMEOUT = $2001; var ForegroundThreadID: DWORD; ThisThreadID: DWORD; timeout: DWORD; AppWnd : THandle; begin if IsIconic(hWnd) then begin ShowWindow(hWnd, SW_RESTORE); end; if GetForegroundWindow <> hwnd then begin // Windows 98/2000 doesn't want to foreground a window when some other // window has keyboard focus if ((Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion > 4)) or ((Win32Platform = VER_PLATFORM_WIN32_WINDOWS) and ((Win32MajorVersion > 4) or ((Win32MajorVersion = 4) and (Win32MinorVersion > 0)))) then begin Result := False; ForegroundThreadID := GetWindowThreadProcessID(GetForegroundWindow, nil); ThisThreadID := GetWindowThreadPRocessId(hwnd, nil); if AttachThreadInput(ThisThreadID, ForegroundThreadID, True) then begin BringWindowToTop(hwnd); SetForegroundWindow(hwnd); AttachThreadInput(ThisThreadID, ForegroundThreadID, False); Result := (GetForegroundWindow = hwnd); end; if not Result then begin // Code by Daniel P. Stasinski SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, @Timeout, 0); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(0),SPIF_SENDCHANGE); BringWindowToTop(hwnd); SetForegroundWindow(hWnd); SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, TObject(Timeout), SPIF_SENDCHANGE); end; end else begin BringWindowToTop(hwnd); SetForegroundWindow(hwnd); end; Result := (GetForegroundWindow = hwnd); end else Result := True; end; ForceForegroundWindow(Application.Handle); |
anyone
中階會員 ![]() ![]() ![]() 發表:1 回覆:63 積分:52 註冊:2007-02-12 發送簡訊給我 |
|
P.D.
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:603 回覆:4038 積分:3874 註冊:2006-10-31 發送簡訊給我 |
|
wameng
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:31 回覆:1336 積分:1188 註冊:2004-09-16 發送簡訊給我 |
P.D. 兄,
請 hWnd 必須以 Application.Handle 代入。 我剛模擬了你的狀況。若使用 Application.Handle 代入,是正常的。 若代入MainForm.Handle 時,會導致上述二次無法最小化。 得不到 Application.Handle 可用 hwnd := GetWindow(hWnd, GW_OWNER); ===================引 用 P.D. 文 章=================== 我使用的正是 wmeng版主所po上來的程式,但這段有個問題,就是程式被呼叫到前景後,如果使用者點選右上角最小化後,再次呼叫到前景是沒有辦法顯示,所以我加了一個 ShowWindow(hwnd, SH_SHOWNORMAL)指令,但以上的做法都無法令被最小化後的程式,當再次被調到前景後,其最小化功能有作用! 所以目前還是沒有辦法解決 |
P.D.
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:603 回覆:4038 積分:3874 註冊:2006-10-31 發送簡訊給我 |
果然,我把ForceForegroundWindow(Form_Main.Handle) 改為 ForceForegroundWindow(Applicaiton.Handle) 之後,一切都ok了,感謝版主全力指點
![]() ===================引 用 wameng 文 章=================== P.D. 兄, 請 hWnd 必須以 Application.Handle 代入。 我剛模擬了你的狀況。若使用 Application.Handle 代入,是正常的。 若代入MainForm.Handle 時,會導致上述二次無法最小化。 得不到 Application.Handle 可用 ? hwnd := GetWindow(hWnd, GW_OWNER);? |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |