启用VCL样式的应用程序在Windows标题栏中出现视觉错误并且显示比例不匹配

9

目前我正在测试启用VCL样式的应用程序的各个方面。

我注意到,当Windows缩放高于默认的96 dpi / 100%时,VCL表单的图标和标题栏文本大小过大 - 两者之间距离太近 - 请参见附加的截图。特别是对于更高的缩放比例,如200%或250%(例如在4K显示器和Windows 10上使用),但即使在144 dpi / 150%的缩放下,这个问题也已经明显可见。

这适用于RAD Studio提供的所有样式。通过项目设置启用了manifest的高DPI感知。

如果我在应用程序中禁用VCL样式,则图标和标题栏文本的大小是正确的。

我错过了什么吗?提供的样式不应该在启用显示缩放的情况下直接正常工作吗?还是有某个设置可以调整以解决此问题?

谢谢,

enter image description here enter image description here


这并不是完美的解决方案,但在每个表单标题前面简单地添加两个空格字符总比什么都不做要好,而且不需要进行 VCL-hacking。 - frogb
这是对问题的评论,不是答案。它没有解决视觉错误的方法;它只是一个笨拙的解决办法。 - Ken White
我也考虑过这个问题,但是如果你的应用程序中有15个不同的表单,并且加载其他带有表单的dll或执行TOpenDialog等操作,那么这不是一个解决方案。 - Tom Major
3个回答

11

@Dalija Prasnikar,感谢您提供的信息和质量控制,但这对我现在没有帮助,我也不想抨击Embarca。我已经在这些年里遇到了他们的错误。我需要在清单中使用DPI感知,并且正在寻找适用于当前10.1版本的解决方案。 - Tom Major
在Style Designer中,有许多子项的Objects\Form\Image\Title\Caption,是否有任何属性可以帮助?我尝试更改其中一些,比如Left或MarginLeft,但似乎没有任何区别。 或者,有人能给我提示VCL样式.pas源代码中标题文本的位置吗?如果这可以修复错误,我也考虑更改.pas源并将其链接到我的项目。谢谢。 - Tom Major
1
我的回答的主要观点是,你必须选择高 DPI 支持或使用 VCL 样式。我们在这里讨论的不是单一问题,而是完全缺乏对高 DPI 的支持,因为它们从一开始就没有被设计支持高 DPI。在高 DPI 下“可以工作”的部分,仅仅是偶然可以工作,并非设计目的。 - Dalija Prasnikar
3
请看来自AlmediaDev的StyleControls。也许这种风格更适合HPDI。 - LU RD
1
我在TFormStyleHook的PaintNC中找到了导致错误的地方,Dalija Prasnikar是正确的。进行了一些测试,看起来有解决方案,将在此处展示它。虽然希望能够在不修补VCL源代码的情况下找到解决方案:(,比如在样式设计器中更改某些属性。 - Tom Major
显示剩余5条评论

3

好的,这是我针对视觉缺陷的解决方案,详见附图。我在Vcl.Forms.pas中进行了3处修复。

第一处修复,标记为// Title bar fix 1,解决了一个问题,即即使在默认96dpi的Windows上使用VCL样式应用程序,图标也无法正确绘制。我能够根据James Johnston关于WM_GETICON和ICON_SMALL2的发现https://dev59.com/IJHea4cB1Zd3GeqPjgVZ#35067909来解决这个问题。感谢你,James!

其他两个修补程序解决了启用显示缩放时图标绘制过大以及图标与标题栏文本之间距离太小的问题。这些修补程序在代码中都有注释,标记为// Title bar fix 2 和 3。GetDpi只是获取当前dpi值的getter函数,我将其从应用程序的C源码中获取。

结果并不完美,但目前来看已经足够了,使用VCL样式应用程序至少在缩放情况下是可以接受的。

感谢大家的帮助。

left original, right 'fixed'

Title bar fix 1

Title bar fix variables

Title bar fix 2

Title bar fix 3


2
拜托了!千万不要发布代码的图片。代码图片是完全没有用的;你无法复制/粘贴,对于视力障碍者来说是不可访问的,它们在许多公司代理后面不可用,对于使用移动设备的人来说绝对很糟糕,它不是搜索的一部分...等等。复制/粘贴/格式化文本比制作屏幕截图、保存文件、创建链接和上传更容易得多。虽然我赞赏你想分享你的解决方案,但请正确地做。 - Ken White
@KenWhite,我理解你的观点,我知道发布截图不是代码的好解决方案。问题是,我实际上只想指出在这个 16k 行的 .pas 文件中我更改了哪些特定位置,并且我希望这些位置能够以某种差异视图的形式呈现,因此我的重点在于位置和差异。 - Tom Major
代码中那些没有过程行号以供您引用其位置的地方? - Ken White

0
这是一个单元,允许在 DPI-aware 应用程序中使用 VCL 样式。

VCL.Styles.DPIAware.pas

要使用该单元,只需将其添加到主窗体的实现 uses 语句中,并将以下代码添加到 FormCreate 处理程序中。

procedure TFrmMain.FormCreate(Sender: TObject);
Var
  StyleDPIAwareness : TStyleDPIAwareness;
begin
  StyleDPIAwareness := TStyleDPIAwareness.Create(Self);
  StyleDPIAwareness.Parent := Self;

默认情况下,该组件会以100%的倍数缩放样式。您可以通过添加以下行来更改:

StyleDPIAwareness.RoundScalingFactor := False;

使用此语句,样式将按照屏幕每英寸像素数的缩放因子进行缩放。大多数样式都可以正常工作,但有些可能会显示一些视觉缺陷。


系统对话框中的窗口标题(如 TColorDialog)缩放不正确,变得过高。因此,确定和取消按钮不可见。此外,使用 uCommonFunctions 会绘制许多其他单元,例如与 SynEdit 相关的单元,这与该单元的功能完全无关。从 uCommonFunctions 中仅使用 resizeBitmap 过程。也许在 VCL.Styles.DPIAware.pas 单元内复制此过程是一个好主意? - Gerrit Beuze

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接