Windows Creator版本更新后,QHD / 4K屏幕上的ExtTextOutW x50性
出于某些奇怪的原因,调用WinAPI的ExtTextOutW函数在高分辨率位图(2560×1440 / 3840×2160)上绘制剪切文本会在使用Creators版本更新更新
Windows 10后导致性能下降~x50.从我的用户的测试和调试日志中可以看出,位图或字体大小的细微差别可能会触发性能损失.
这是一个显示性能命中的调试日志: 10/05/2017 15:51:50 [ 63227,186] : Calculate Rect 10/05/2017 15:51:50 [ 63227,190] : Rect : Left=263,Top=504,Right=3561,Bottom=2155 10/05/2017 15:51:50 [ 63227,193] : Set Shadow Color 10/05/2017 15:51:50 [ 63227,198] : Render Text Shadow 10/05/2017 15:51:50 [ 63236,650] : Set Text Color 10/05/2017 15:51:50 [ 63236,661] : Render Text "Kingdom come Deliverance" 10/05/2017 15:51:50 [ 63246,062] : Rendering complete 正如您在日志中看到的那样,对ExtTextgOutW的单次调用需要大约9.5ms,而同一调用在创建者更新之前的1ms内完成. 以下是您可以与上面的调试输出进行比较的实际代码: {$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:log.TextRender.txt','Calculate Rect');{$ENDIF} cRect := Rect(X,Y,Width+X,MainForm.Monitor.Height-(1+(MainForm.Monitor.Height div 540))); {$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:log.TextRender.txt','Rect : Left='+IntToStr(cRect.Left)+',Top='+IntToStr(cRect.Top)+',Right='+IntToStr(cRect.Right)+',Bottom='+IntToStr(cRect.Bottom));{$ENDIF} {$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:log.TextRender.txt','Set Shadow Color');{$ENDIF} srcColor := txtCanvas.Font.Color; txtCanvas.Font.Color := OutLineColor; {$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:log.TextRender.txt','Render Text Shadow');{$ENDIF} Windows.ExtTextOutW(txtCanvas.Handle,X,Y+(MainForm.Monitor.Height div 540),ETO_CLIPPED,@cRect,@S[1],I,nil); {$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:log.TextRender.txt','Set Text Color');{$ENDIF} txtCanvas.Font.Color := srcColor; {$IFDEF TEXTRENDERTRACE}DebugMsgFT('c:log.TextRender.txt','Render Text "'+S+'"');{$ENDIF} Windows.ExtTextOutW(txtCanvas.Handle,'Rendering complete'+CRLF);{$ENDIF} 此代码通过将相同的文本呈现两次,并且Y偏移和颜色略有不同,从而实现了非常简单的阴影效果. 以下是我的论坛用户的完整讨论,我们尝试在各种硬件上调试问题(帖子中包含其他调试日志): 我们在DPI设置为100%的情况下进行了测试,以确保触发器与Creators Edition中引入的DPI更改无关. 有谁知道是什么引发了这个?是否有解决方法? *****更新1 ***** 至少在初始测试中,“DrawTextExW”似乎也受到性能损失的影响.在测试过程中使用的字体是Arial,性能问题似乎与字体的大小有关,因为用户报告在屏幕上添加更多较小尺寸的行(更多文本以较低分辨率呈现)可以大大提高性能. *****更新2 ***** 我写了一个小工具来描述这个问题,您可以在这个GitHub存储库中找到它: 似乎问题取决于字体大小,例如,在2560×1440屏幕上,渲染一行“Arial”字体文本,大小为“35”21ms来渲染,而大小为“34”需要2ms. 这将呈现为具有32位像素格式的Delphi TBitmap的HDC,并且禁用剪辑仅对性能产生轻微影响. *****更新3 ***** Sebastian Z的答案确实恢复了预创作者版本的性能水平,我已经更新了GitHub上的示例代码以反映他的答案,但我已经能够使用Windows 7 64位和1920×1080屏幕重现该问题,所以它是不限于Windows 10创建者版或高分辨率显示器,当字体质量设置为ANTIALIASED时,只需触发阈值更高.在我在Windows 7下的测试中,使用字体Arial,触发点的字体大小为“109”(快),而字体大小为“110”(x10速度较慢或性能较差).在使用Sebastian Z的答案来禁用cleartype之后,Windows 10中存在相同的触发阈值.
Delphi使用lfQuality:= DEFAULT_QUALITY;创建字体.默认质量过去是抗锯齿质量.但是,自从Windows 10 Creators更新后,现在默认为cleartype.这很慢.所以解决方案是手动强制抗锯齿质量.
如果您使用的是当前的Delphi版本,则只需设置Font.Quality属性即可: Procedure RenderText(oBitmap : TBitmap; X,Y : Integer; cRect : TRect; S : WideString; testFunction : Integer; TxtEffect : Integer; EffectColor : TColor; Clipping : Boolean); // [...] begin obitmap.Canvas.Font.Quality := fqClearType; 在较旧的Delphi版本中,它有点复杂: var lf: TLogFont; begin if GetObject(oBitmap.Canvas.Font.Handle,SizeOf(TLogFont),@lf) = sizeof(TLogFont) then begin lf.lfQuality := ANTIALIASED_QUALITY; oBitmap.Canvas.Font.Handle := CreateFontIndirect(lf); end; 这在Windows 10 Creators Update中非常棘手,因为ClearType文本并不总是合适,并且可能导致意外结果. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 将PDF文件/对象插入Microsoft Excel时出现“无法
- 如何将分享按钮添加到Windows 10移动UWP应用程序
- 在.net framework 4.0下运行.net framework 1.1程
- Windows上的应用程序颜色(背景,按钮等)指南?
- windows – 为什么我不在域控制器上运行setspn.e
- windows-runtime – WinRT中SecureString的等价物
- windows – 从完全内存转储中提取进程转储
- 在Windows中,如何输入Unicode基本多语言平面之外
- windows-xp – 如何禁止拖放Windows XP文件夹?
- 我在Vista Home Premium上开发.NET有什么损失