淺談無效化一個空窗口的后果
有時候,你可能會注意到這樣一個現象:桌面上的所有窗口都刷新了自身并產生了閃爍。
導致這個現象的原因之一是一個所謂的空句柄窗口 Bug。
如果你研究過 Win32 SDK 編程,則你應該比較熟悉這個函數:InvalidateRect。
調用這個函數可以通知窗口管理器:某個窗口的內容發生了變化,需要重新繪制了。在這個函數中,你還可以傳入一個矩形坐標來表明你希望將窗口上的哪個區域標記為無效。
這通常是在窗口中渲染的數據的狀態發生了變化,并且你希望窗口使用新數據重新繪制時完成的。
但是,如果你將 NULL 作為窗口句柄傳遞給 InvalidateRect 函數,則將其視為與早期版本的 Windows 兼容的特殊情況:它使桌面上的所有窗口失效并重新繪制它們。
因此,如果你嘗試使窗口無效,但錯誤檢查或計時錯誤并最終錯誤地傳遞了NULL,則結果將是整個屏幕閃爍。
更奇怪的是,將 NULL 作為第一個參數 ValidateRect 傳遞具有使所有窗口無效的相同行為。(是的,它是“有效化”功能,但它卻執行的是無效化)。這個行為也是出于相同的兼容性原因考慮。
這是另一個程序如何依賴錯誤或未文檔化行為的例子,在這種情況下,由于沒有嚴格的參數驗證,早期版本的 Windows 處理 NULL 參數的特殊方式。
修改窗口管理器中的幾乎任何內容都增加了很有可能會有許多程序依賴于舊行為,也許完全是偶然的,破壞這些程序意味著大公司的憤怒電話,因為他們的工廠控制軟件停止了工作。那么,最好還是不要亂動這些古老的代碼為妙。
總結
請立即全文搜索你的代碼中的所有 InvalidateRect 調用,看看第一個參數是否為 NULL。
反正我等會就會去這樣做。感謝作者給我解答了一個窗口閃爍的大謎團。