主頁 > .NET開發 > 如何將Win32App的背景顏色初始化為白色以外的顏色以避免在ShowWindow上閃爍?

如何將Win32App的背景顏色初始化為白色以外的顏色以避免在ShowWindow上閃爍?

2021-11-03 02:35:07 .NET開發

我正在研究為什么在運行我的 Windows 應用程式時,它在呈現實際應用程式之前(即,在收到 WM_ERASEBKGND 和 WM_PAINT 之前)有一小段白色背景閃爍。

現在,我剛剛注意到這個問題也存在于 Visual Studio 創建的默認示例應用程式中。至少在 Windows 10,21H1(在 VS2008 和 VS2013 中)下運行時我就是這種情況。

在創建“新的 Win32 專案”之后,您唯一需要做的就是更改視窗類的背景顏色,例如,更改為紅色:

    //wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW 1);
    wcex.hbrBackground = (HBRUSH) CreateSolidBrush(RGB(255, 0, 0));

然后在 WndProc 中添加一個帶有 Sleep 的 WM_ERASEBKGND:

    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        // TODO: Add any drawing code here...
        EndPaint(hWnd, &ps);
        break;
    case WM_ERASEBKGND:
        Sleep(1000);
        return DefWindowProc(hWnd, message, wParam, lParam);

睡眠夸大了問題,導致白色背景顯示至少一秒鐘。之后,紅色背景按預期繪制。

在運行具有這些更改的應用程式時,我包含了一個簡短的如何將 Win32 App 的背景顏色初始化為白色以外的顏色以避免在 ShowWindow 上閃爍?

這意味著 Windows 確實知道并尊重 hbrBackground,這很棒!出于某種奇怪的原因,它只是沒有清除它,而是將其清除為白色。

(順便說一句,我使用“255 255 255”設定檢查了注冊表中的所有系統顏色(HKEY_CURRENT_USER\Control Panel\Colors HKEY_CURRENT_USER\Control Panel\Desktop\Colors)并強行更改它們以查看是否會更改初始白色背景。但沒有運氣。這讓我得出結論,白色背景不是系統顏色。)

無論如何,以上引導我嘗試在 ShowWindow 之后以編程方式調整視窗大小。但是由于我不希望它在打開時閃爍,所以在螢屏外執行 ShowWindow。

所以這里是替換常規 ShowWindow(..) 的代碼:

    int x0 = GetSystemMetrics(SM_XVIRTUALSCREEN); 
    int x1 = GetSystemMetrics(SM_CXVIRTUALSCREEN); 
    
    RECT rect;
    GetWindowRect(hWnd, &rect); 

    // resize and move off-screen
    SetWindowPos(hWnd, NULL, x1-x0, 0, 0, 0, SWP_NOREDRAW );    
      
    // show window
    ShowWindow(hWnd,nCmdShow);  
    
    // restore and redraw
    SetWindowPos(hWnd, NULL, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0 ); 

現在,我稱之為黑客。然而,它不依賴于 WM_ERASEBKGND 或 WM_PAINT,所以應該不存在時序問題。此外,該視窗的顯示與常規 ShowWindow(...) 完全一樣,只是使用正確的 hbrBackground,這正是我想要的。

這是@ 25Hz 的樣子:

如何將 Win32 App 的背景顏色初始化為白色以外的顏色以避免在 ShowWindow 上閃爍?

請注意,沒有白色背景的閃光。

請注意,我已經嘗試撰寫代碼來滿足虛擬桌面/多顯示幕的需求,但還沒有實際測驗過。

但不幸的是,一切都不是很好和花花公子。在我寫這個答案的時候,我用 OBSStudio 錄制 @ 60Hz 做了很多試運行,并瀏覽了鏡頭。在那里,我發現一個在打開的視窗框架內僅顯示垃圾(顯然來自 Chrome),僅顯示一幀。這是一個放慢的重播:

如何將 Win32 App 的背景顏色初始化為白色以外的顏色以避免在 ShowWindow 上閃爍?

我難住了。也許這才是真正的問題?

uj5u.com熱心網友回復:

一個更有爭議的答案可能是這只是 Windows 中的一個錯誤。

作為參考,(除了我已經發布的來自 Windows 10 的現有 GIF)這里是在 Windows XP、Windows 7 和 Windows 11 中使用和不使用后臺擦除運行的示例應用程式的錄音。

視窗 XP:

Windows XP:無 WM_ERASEBKGND/WM_PAINT:OK(無白色背景) 如何將 Win32 App 的背景顏色初始化為白色以外的顏色以避免在 ShowWindow 上閃爍?

Windows XP:使用 WM_ERASEBKGND:OK(無白色背景) 如何將 Win32 App 的背景顏色初始化為白色以外的顏色以避免在 ShowWindow 上閃爍?

Windows 7的:

Windows 7:沒有 WM_ERASEBKGND/WM_PAINT:不正常(白色背景) 如何將 Win32 App 的背景顏色初始化為白色以外的顏色以避免在 ShowWindow 上閃爍?

Windows 7:使用 WM_ERASEBKGND:不正常(白色背景) 如何將 Win32 App 的背景顏色初始化為白色以外的顏色以避免在 ShowWindow 上閃爍?

Windows 7:使用 WM_ERASEBKGND 睡眠:不正常(白色背景) 如何將 Win32 App 的背景顏色初始化為白色以外的顏色以避免在 ShowWindow 上閃爍?

禁用 Aero 的 Windows 7:

禁用 Aero 的 Windows 7:無 WM_ERASEBKGND/WM_PAINT:正常(無白色背景) 如何將 Win32 App 的背景顏色初始化為白色以外的顏色以避免在 ShowWindow 上閃爍?

禁用 Aero 的 Windows 7:使用 WM_ERASEBKGND:OK(無白色背景) 如何將 Win32 App 的背景顏色初始化為白色以外的顏色以避免在 ShowWindow 上閃爍?

Windows 7 with Aero disabled: With WM_ERASEBKGND Sleep: OK (no white background) 如何將 Win32 App 的背景顏色初始化為白色以外的顏色以避免在 ShowWindow 上閃爍?

Windows 11 (with Animation disabled):

Windows 11: Without WM_ERASEBKGND/WM_PAINT: NOT OK (white background) 如何將 Win32 App 的背景顏色初始化為白色以外的顏色以避免在 ShowWindow 上閃爍?

Windows 11: With WM_ERASEBKGND: OK (no white background) 如何將 Win32 App 的背景顏色初始化為白色以外的顏色以避免在 ShowWindow 上閃爍?

Windows 11: With WM_ERASEBKGND Sleep: NOT OK (white background) 如何將 Win32 App 的背景顏色初始化為白色以外的顏色以避免在 ShowWindow 上閃爍?

I've added Sleep to tests where it was hard to see the issue.

To sum up:

  • Windows XP: No issue. Everything seems to work as expected.
  • Windows 7: Issue occurs when Aero is enabled (Windows 7 theme), but not when it is disabled (Classic theme).
  • Windows 10: Issue occurs for all tests.
  • Windows 11: Issue occurs, but works without Sleep added. Most likely since this was running on a faster machine.

因此,雖然我無法從這些測驗中得出任何可靠的結論,但看起來這種行為確實是在帶有 Aero 的 Windows 7 中引入的

如果有人可以揭穿這一說法,請在下面發表評論。

uj5u.com熱心網友回復:

我做了一些更多的測驗,并想發布這個問題的潛在答案。現在,這主要基于@JonathanPotter 的建議,因此完全歸功于他。雖然它并沒有真正解決問題,但它確實減輕了很多。

現在,理想情況下,如果 Windows 能夠簡單地使用正確的初始背景顏色渲染視窗,那就太好了,但是無論我多么努力地嘗試,我都只能通過使用 WM_ERASEBKGND 或 WM_PAINT 來更新背景顏色。

因此,顯示視窗(即使用 ShowWindow)和實際清除背景(WM_ERASEBKGND)之間的時間延遲似乎是問題的關鍵。因此,對其進行概要分析是有意義的。我通過記錄呼叫 ShowWindow 和使用 QueryPerformanceCounter 到達 WM_ERASEBKGND 之間的時間差來做到這一點。

因此,在運行 Window 10 的 i7-4960HQ CPU @ 2.60GHz 上,ShowWindow 和 WM_ERASEBKGND 之間的時間在100 - 317ms之間它波動很大。這是一個普通的 Win32 示例應用程式,內置 Release 沒有任何 Sleeps 或類似的東西,但使用紅色 hbrBackground 來顯示問題。這意味著在繪制紅色背景之前,白色背景在幾幀內清晰可見。這是@ 25Hz 捕獲的影片 gif:如何將 Win32 App 的背景顏色初始化為白色以外的顏色以避免在 ShowWindow 上閃爍?該影片中的 3 幀可見白色背景。

現在潛在的解決方法是在顯示視窗之前使用 SetWindowPos 和 RedrawWindow 的組合。

對于我的測驗,我只是在呼叫 ShowWindow(..) 之前添加了這兩行:

   SetWindowPos(hWnd, NULL, 0,0,0,0,   SWP_NOMOVE | SWP_NOSIZE | SWP_NOREDRAW);
   RedrawWindow(hWnd, NULL, 0, RDW_INVALIDATE |  RDW_ERASE);

盡管 RedrawWindow 似乎沒有任何區別。再次分析,ShowWindow 和 WM_ERASEBKGND 之間的時間現在是10 - 23ms10 倍加速!

再次,捕獲的影片 gif(使用 SetWindowPos)@ 25Hz:如何將 Win32 App 的背景顏色初始化為白色以外的顏色以避免在 ShowWindow 上閃爍? 這清楚地表明白色背景的閃光消失了,因此問題已解決。這就像白天和黑夜。

Now, I would argue that this is not a fix, but rather a workaround. Since the underlying problem of Windows using a white background color is still there. And since this is a timing issue, I can easily imagine that the white background could show up again, say if the system was sluggish or busy doing other stuff. Similarly, having a faster system means you that you are less likely to see this in the first place, effectively hiding the issue. But simply setting a breakpoint in WM_ERASEBKGND will still show you a white window.

Also, I have no explanation for the speed-up. I tracked the number of messages in the message pump, and they are the same in both scenarios.

Now, I'm still hoping for a better fix. I find it hard to believe that the Microsoft engineers found it cool to fill all freshly created Windows with a hardcoded 0xFFFFFF, so I'm hoping that this color is actually read from somewhere, and thus possible to change, so the initial background matches the hbrBackground.

Please feel free to post alternative answers, questions, or suggestions. I will of course update this thread if I figure out anything else.

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/345297.html

標籤:登录

上一篇:將文本設定為RichEdit控制元件時處理錯誤

下一篇:Windows:限制一個視窗可以有多少個區域?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more