2013-09-26 34 views
2

我正在寫一個Win7桌面應用程序,並希望從無縫過渡到窗口 - 全屏(反之亦然),並且主要通過調用SetWindowLongPtr更新其樣式,然後MoveWindow更新其大小和位置。問題是窗口閃爍一幀以顯示其風格已更新,但未顯示新的尺寸和位置。下一幀一切看起來正確,但我試圖避免這個單幀神器。如何以原子方式更新HWND的風格和位置?

我試過顛倒了我調用API的順序,但它只是改變了工件的外觀。我也嘗試隱藏窗口,調用API,然後顯示窗口,但這隻會導致窗口消失一幀。

我知道一個選擇是創建一個具有所需屬性的新窗口,然後銷燬舊的窗口,但我想找到一個更便宜的選擇。

那麼有什麼辦法可以調用這些API並讓它們在原子上被視覺反射?作爲獎勵,將多個生成的WM_SIZE消息合併成單個事件會很好,但我可以在消息處理程序中自己管理它。

回答

2

在Windows中很難做到這一點很困難,尤其是Vista以後,因爲DWM會讓事情變得複雜。在您找到適合您的解決方案之前,通常需要經歷試驗和錯誤。

SetWindowPos有一個SWP_NOREDRAW標誌,該標誌防止響應該調用重繪窗口。因此,您可以先嚐試更改位置,然後更新樣式,最後再調用第三次重新繪製窗口的新位置。例如,

SetWindowPos(hWnd, 0, x, y, w, h, SWP_NOREDRAW | SWP_NOZORDER); 
SetWindowLongPtr(hWnd, GWL_STYLE, dwNewStyles); 
RedrawWindow(hWnd, 0, 0, RDW_INVALIDATE | RDW_FRAME); 
+0

最準確的答案,但我無法獲得在多臺機器上始終無僞造的任何內容,包括使用RedrawWindow方法。 – MooseBoys

0

你是什麼意思的「窗口全屏」?它是否與最大化一樣?

如果是這樣,ShowWindow(hwnd, SW_MAXIMIZE)

+0

不,我的意思是WS_POPUP樣式,客戶端矩形等於顯示器矩形。也稱爲[無邊界全屏](http://pcgamingwiki.com/wiki/Borderless_fullscreen_windowed),這會在使用DirectX時產生一些效率。它看起來像SW_MAXIMIZE確實可以替代MoveWindow,但它並沒有消除這個工件,因爲我仍然需要先調整窗口樣式。 – MooseBoys

1

MSDN說:

某個窗口是緩存數據,所以更改也使用,直到調用SetWindowPos 功能 SetWindowLongPtr將不能生效。

所以這個應該工作。也許嘗試使用SetWindowPos而不是MoveWindow。

當你得到由這些調用引起的事件時,你是否在做任何有趣的窗口過程?特別是,你是否在「固定」尺寸或類似的東西?

+0

我也嘗試了SetWindowPos,並且它產生了相同的結果。我在wndproc中唯一處理的是處理WM_SYSCHAR的Alt + Enter命令。我會「修復」尺寸,但只有在小於128像素的情況下才能修復尺寸,所以在這種情況下不會受到影響(通過調試器進行驗證)。 – MooseBoys

1

結賬WM_SETREDRAW;使用它來禁用重繪,更改窗口樣式,然後調用RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN)以原子方式顯示它們。

+0

該窗口可能會忽略此消息 –

相關問題