2008-11-05 92 views
3

我想確定某個窗口對用戶是可見還是隱藏/遮擋。在Windows XP中,我將使用GetClipBox()函數並檢查NULLREGION或空RECT返回值。這工作得很好,但在Windows Vista上它不起作用,如果另一個窗口遮擋窗口。在這種情況下,GetClipBox()返回一個非空RECT的SIMPLEREGION。確定Vista中的窗口可見性

有人知道爲什麼這不是在Vista上工作,或者如果有另一種方法來檢查用戶是否可以看到一個窗口?

回答

2

原因很簡單GetClipBox()沒有返回啓用NULLREGION與DWM是因爲你沒有被修剪! DWM的全部要點是每個窗口(不是孩子,就像按鈕或編輯框)獲取它自己的緩衝區來繪製,所以前景窗口可以移動而不必填充窗口後面的窗口。

作爲一個簡單的例子,當鼠標懸停在任務欄中的窗口條目上並且在預覽中看到它正在更新時,將其懸停在任務欄上。

另請注意,使用玻璃邊緣,您的窗戶可以完全被其他窗戶覆蓋並仍然可見! (你甚至不能測試客戶區域,因爲延伸的玻璃,就像Windows Media Player使用的那樣 - 調整它的大小,使其看起來像它的整個區域一樣小!)當然,分層窗口(從XP開始)和自定義窗口區域意味着這可能總是如此,但現在它是默認的。

摘要/ TL; DR:

如果你正在做大量動畫/奇特的效果,並希望減少CPU使用的DWM下運行時,可能是你能做的最好的是,當你的應用程序失去前景檢測並回退到CPU更友好的更新(不更新!如果你得到一個WM_PAINT,並忽略它,因爲你在後臺,你不會得到一個,當你被激活!)。

+0

感謝您的詳細解釋!正如你猜測的那樣,我的應用程序正在執行CPU密集型動畫,所以當我的窗口不可見時,我嘗試減少CPU使用率。檢查我的應用程序是否是前臺窗口聽起來像是一個合理的工作,我會嘗試一下。 – flashk 2008-11-22 19:17:42

1

做一個有點麻煩的方法是獲取要檢查的窗口的位置/大小,然後循環遍歷所有高於Z順序的窗口,並計算窗口的哪些部分蓋。

2

在您安裝Vista時,桌面窗口管理器組合是否打開?我猜想是的,如果你關掉它,你會得到預期的XP行爲。問題是,在DWM組合的Vista下,窗口的處理方式已經發生了很大的變化,我不認爲有一種簡單的方法可以實現你想要的功能。

1

在您安裝Vista時,是否在桌面上打開了 窗口管理器組合? 我猜測它是,而如果你關掉它,你會得到 預期的XP行爲。問題是 在Vista下使用DWM組合, 窗口處理的方式有 改變了很多,我不認爲 會有一個簡單的方法來得到你想要的 。

是的,DWM在我的機器上啓用。我嘗試了以下測試你的假設:

  1. 右鍵點擊我的應用程序,並選擇「屬性」
  2. 點擊「兼容性」選項卡
  3. 啓用「禁用桌面組合」複選框
  4. 點擊「Apply」

之後GetClipBox()函數正常工作。所以你的直覺是正確的。我發現,我可以用我的應用程序內的下列函數編程方式執行此:

DwmEnableComposition(DWM_EC_DISABLECOMPOSITION); 

然而,這同時我的應用程序正在運行,這是不可取的禁用透明效果。我寧願不那麼突兀的解決方案。

無論如何,感謝您的建議!

0

由於您知道來自GetClipRect的輸出在XP和Vista上(啓用和不啓用DWM)都可以創建一個函數,以確定這個函數根據操作系統採用不同的路徑。在僞代碼:

function bool IsWindowVisible() 
{ 
    bool isVisible = false; 

    if (OSVersion == "XP") 
    { 
     // GetClipRect tests which run on XP and set isVisible 
    } 
    else if (OSVersion == "Vista") 
    { 
     if (DWMCompisitionEnabled == true) 
     { 
     // GetClipRect tests for Vista with DWM enabled and set isVisible 
     } 
     else 
     { 
     // GetClipRect tests for Vista with DWM disabled and set isVisible 
     } 
    } 
    return isVisible; 
}