全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:8412
推到 Plurk!
推到 Facebook!

SetForegroundWindow的問題

答題得分者是:wameng
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#1 引用回覆 回覆 發表時間:2007-08-01 15:37:08 IP:61.67.xxx.xxx 未訂閱
請問各位:

我設計兩支程式,一支在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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2007-08-01 18:40:07 IP:61.222.xxx.xxx 訂閱
應該是這樣吧!由於你直接調用更改視窗狀態的API。
導致 Dlephi 與 Window 並不同步。

應該在 SetForeGroundWindow 之前做IsIconic的判斷
if IsIconic(XX) then Restore else SetForegroundwindow

試試。
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#3 引用回覆 回覆 發表時間:2007-08-01 22:27:06 IP:61.67.xxx.xxx 未訂閱
本來我的程式是這樣做的
<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

發送簡訊給我
#4 引用回覆 回覆 發表時間:2007-08-01 23:47:21 IP:61.31.xxx.xxx 訂閱
很久以前遇到過,也忘記詳細是怎麼弄。
多試試。

Restore 後,在SetForegroundWindow 使 Window Active。

if IsIconic(hwnd) then ShowWindow(hwnd,SW_RESTORE);
SetForegroundWindow(hWnd);


P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#5 引用回覆 回覆 發表時間:2007-08-02 01:16:53 IP:61.67.xxx.xxx 未訂閱
呵呵呵,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

發送簡訊給我
#6 引用回覆 回覆 發表時間:2007-08-02 10:41:24 IP:61.222.xxx.xxx 訂閱
   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

發送簡訊給我
#7 引用回覆 回覆 發表時間:2007-08-02 11:09:00 IP:61.222.xxx.xxx 訂閱
或者用

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

發送簡訊給我
#8 引用回覆 回覆 發表時間:2007-08-02 13:13:56 IP:59.127.xxx.xxx 未訂閱
用SetWindowPos(Handle, hwnd_TopMost,......)
再加上SetForegroundWindow(Handle)
就可以了。
若不行的話,在上面那兩句的中間再加上SetActiveWindow(Handle)
即可,這方法一定可以的。
編輯記錄
anyone 重新編輯於 2007-08-02 13:15:08, 註解 無‧
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#9 引用回覆 回覆 發表時間:2007-08-02 18:47:00 IP:61.67.xxx.xxx 未訂閱
我使用的正是 wmeng版主所po上來的程式,但這段有個問題,就是程式被呼叫到前景後,如果使用者點選右上角最小化後,再次呼叫到前景是沒有辦法顯示,所以我加了一個 ShowWindow(hwnd, SH_SHOWNORMAL)指令,但以上的做法都無法令被最小化後的程式,當再次被調到前景後,其最小化功能有作用!
所以目前還是沒有辦法解決
wameng
版主


發表:31
回覆:1336
積分:1188
註冊:2004-09-16

發送簡訊給我
#10 引用回覆 回覆 發表時間:2007-08-02 22:35:33 IP:61.31.xxx.xxx 訂閱
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

發送簡訊給我
#11 引用回覆 回覆 發表時間:2007-08-03 09:54:36 IP:61.67.xxx.xxx 未訂閱
果然,我把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);?


系統時間:2024-04-16 22:05:35
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!