2009-05-01 42 views
12

在Windows中,是否可以設置窗口A,使其始終位於窗口B的頂部,但允許其他窗口正常工作,並在活動時顯示在兩者的頂部。一個窗口可以總是在另一個窗口上面嗎?

換句話說,我想要兩個窗口之間的父子關係。這可以在不使窗口A成爲窗口B的孩子,MDI風格的情況下完成嗎?窗口B不是我的(Internet Explorer),並在我試圖通過SetParent實現此目的時將對話框A的圖形擰緊。

我想我與來自MSDN forum post這個想法破解它,但可惜的窗口A仍然總是在一切之上,而不僅僅是窗口B.

// Place window A on top 
SetWindowPos(hWndWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 
// Place window B underneath it 
SetWindowPos(hWndParent, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); 

這可能嗎?

+0

不幸的是,我不認爲有辦法做到這一點。 – Charlie 2009-05-03 03:27:19

回答

0

你可以訪問窗口的Z順序嗎?

我不記得窗口的默認z順序,但我認爲這是1.您可能能夠IE設置爲-1和您的應用程序爲0

0

試試這個:

// Place window A on top of window B 
SetWindowPos(hWndA, hWndB, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 

第二個窗口句柄參數指定Z順序中的下一個窗口。

注意這實際上並不改變窗口的父子關係 - 但是你可以模擬它。

+0

這是它的一次(但它做了一次沒有它反正)。點擊IE將它帶到我的窗口前:( – Mat 2009-05-01 20:30:45

3

當您的窗口的Z順序(或大小或位置)發生變化時,它應該收到WM_WINDOWPOSCHANGING消息。如果處理該消息,則可以修改窗口移至的最終Z順序(​​或大小或位置)。

爲了說明,在hWndA的窗口過程:

case WM_WINDOWPOSCHANGING: 
    DefWindowProc(hWnd, msg, wParam, lParam); 
    WINDOWPOS *p = (WINDOWPOS*)lParam; 
    p->hwndInsertAfter = hWndB; 
    p->flags &= ~SWP_NOZORDER; 
    return 0; 

應在Z順序hWndB後插入hWndA任何時候hWndA的位置變化。

+0

Mat沒有自己的父窗口,所以他不能改變「A」的winproc。但是,也許父母的某種類型的鉤子會起作用? – Aardvark 2009-05-04 17:45:24

+0

其實,他說他擁有A並且想讓它看起來像是B的孩子,這不是他的(Internet Explorer)。我認爲A會收到A的z順序在B前面移動的通知。 – 2009-05-04 20:16:02

2

在Vista之前,一種方法是使用SetWindowsHookEx,並鉤住WH_CBTWH_CALLWNDPROC鉤子,然後在檢測到Z順序變化時採取適當的措施。然而,這不適用於Vista(據我所知,谷歌搜索)。

唯一的其他解決方案,我能想到的是要建立一個計時器,每隔幾秒鐘火,然後當您收到WM_TIMER,您使用GetNextWindow找出哪個窗口是你背後詢問系統。如果它不是IE,請致電SetWindowPos將您的窗口放置在IE上方(我假設您有一個關於您關心的IE窗口的HWND-記住可以有多個IE窗口)。

如果人們試圖將您的窗口放在前面,這會導致問題 - 它會翻轉回到IE上方。在這種情況下,在您的代碼中,您可以處理WM_ACTIVATE並嘗試更改IE窗口的Z順序,使其位於窗口下方(請撥SetWindowPos移動IE窗口,使其位於窗口當前窗口之上)。出於安全原因,這種解決方案可能充滿了問題,因爲Windows可能會試圖阻止您搞亂另一個進程的窗口。另一方面,SetWindowPos的MSDN文檔不明確提到您不能操縱另一個進程的窗口。儘管可能有一些模糊的限制。

即使此計時器的黑客,你將有效地在你的應用程序一個忙等待循環(與頻繁的WM_TIMER消息),這通常是一個壞的事情,尤其是對於筆記本電腦的電池壽命等等(因爲你阻止CPU進入睡眠狀態,等等)。

我會說沒有好的方法來做到這一點,任何你可能會工作的東西都會變得脆弱並引發問題。 我強烈建議不要嘗試去做。是否有可能讓你的程序進入IE的某種插件或工具欄?

NB尤其要注意的是,如果沿着這條路線走下去,SetWindowsHookEx會在系統級別上造成性能損失。

12

不會產生所有權關係嗎?

SetWindowLong(hwndChild, GWL_HWNDPARENT, hwndOwner) 

窗口可以在不同的進程中,你可以從任何進程調用它。這將確保子窗口始終位於所有者窗口之上。這與實際創建父/子關係的SetParent不同。 Read through this article(它從1993年開始,但仍然大部分是正確的),以查看所有權與父母之間的區別。

1

莫里斯的答案是最好的,但缺少重要的一步。當您在窗口上調用show作爲疊加層時,您需要調用具有該參數的show方法。您需要定義一個實現IWin32Window接口的類,並創建一個新的實例。接口關心的唯一事情是Handle,因此只需將它設置爲IE窗口的句柄,它應該工作得很好

0

如果父子關係是由SetWindowPos()函數自己完成的,那麼您的願望可以實施。

相關問題