【问题标题】:Visual bug in Windows title bar with VCL Styles enabled application and display scaling启用 VCL 样式的应用程序和显示缩放的 Windows 标题栏中的视觉错误
【发布时间】:2017-05-04 21:18:51
【问题描述】:

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

我注意到,Windows 缩放比例高于默认的 96 dpi/100%, VCL 表单的图标和标题栏文本太大 - 两者要靠在一起 - 请参阅随附的屏幕截图。对于 200% 或 250% 等更高的缩放比例尤其如此(例如,用于 4K 显示器和 Windows 10),但即使缩放比例为 144 dpi/150%,问题也已经显现。

RAD Studio 提供的所有样式都是如此。清单的高 Dpi 感知通过项目设置启用。 如果我在应用程序中禁用 VCL 样式,则图标和标题栏文本的大小正确。

我在这里遗漏了什么吗?在启用显示缩放的情况下,交付的样式是否应该在没有此类显示错误的情况下工作?或者有什么设置我可以调整来解决这个问题。

谢谢,

【问题讨论】:

  • 这绝不是完美的,但只是在每个表单的标题前面添加两个空格字符总比没有好,并且不涉及 VCL 黑客。
  • 这是对问题的评论,而不是答案。它不解决修复视觉错误的问题;这只是一个笨拙的解决方法。
  • 我也想过,但如果你在应用中有 15 种不同的表单,并使用表单加载其他 dll 或执行 TOpenDialog 等,不,这不是解决方案。

标签: delphi c++builder vcl vcl-styles


【解决方案1】:

VCL 样式不能正确支持高 DPI 缩放。

如果您使用 VCL 样式,则应从应用程序清单中移除高 DPI 意识。


要求对 VCL 样式提供一般高 DPI 支持的 QP 报告: VCL styles don't scale properly under high DPI configurations

NC区相关QC报告:Styled form's non-client area incorrectly scaled under High DPI

【讨论】:

  • @Dalija Prasnikar,感谢您提供的信息和您的 QC,但这现在对我没有帮助,而且我对 Embarca 不感兴趣。抨击任何一个,多年来我已经与他们的错误分享了我的份额。我需要在 manifest 中使用 DPI 感知,并且我正在寻找适用于当前 10.1 版本的解决方案。
  • - 在样式设计器中,Objects\Form\Image\Title\Caption 有很多子项,有什么属性可以帮助吗?我尝试更改其中的一些,例如 Left 或 MarginLeft,但似乎没有任何区别。 - 或者,有人可以提示我在 VCL 样式 .pas 源中放置标题文本的位置吗?如果这可以修复错误,我还会考虑更改 .pas 源并将其链接到我的项目。谢谢
  • 我回答的要点是您必须选择高 DPI 支持或使用 VCL 样式。这不是我们在这里讨论的单一问题。完全不支持高 DPI,因为它们从一开始就没有设计为支持高 DPI。在高 DPI 下“工作”的部件只是偶然工作而不是设计。
  • 看看 AlmediaDev 的 StyleControls。也许样式更适合 HPDI。
  • 我在PaintNC的TFormStyleHook中找到了负责该bug的地方。 Dalija Prasnikar 是对的。做了一些测试,它看起来很有希望找到一个解决方案,当它工作时会在这里展示它。虽然希望在不修补 VCL 源的情况下找到解决方案 :(,比如更改样式设计器中的某些属性。
【解决方案2】:

好的,这是我对视觉错误的解决方案,请参阅随附的屏幕截图。我在 Vcl.Forms.pas 的 3 个地方做了修复。

第一个修复,注释为 // 标题栏修复 1,解决了在具有 VCL 样式应用程序的默认 96dpi Windows 上未正确绘制图标的问题,即使没有缩放。我可以根据 James Johnston 关于 WM_GETICON、ICON_SMALL2 的发现来解决这个问题, https://stackoverflow.com/a/35067909 谢谢詹姆斯!

另外两个修复解决了启用显示缩放后图标绘制过大,以及图标与标题栏文本之间的距离过小的问题。这些是代码中用 // 标题栏修复 2 和 3 注释的修复。 GetDpi 只是当前 dpi 值的获取器,它是我从应用程序中的 C 源代码中获取的。

结果绝不是完美的,但现在可以了,这样 VCL 风格的应用程序至少在规模化的情况下是可以接受的。

感谢大家的意见。

【讨论】:

  • 看在皮特的份上!不要永远发布代码图片。代码图像绝对没用;您不能复制/粘贴,有视力障碍的人无法访问它,它们在许多公司代理后面不可用,它们对于使用移动设备的人来说绝对是臭的,它不是搜索的一部分......等等。复制/粘贴/格式化文本比截屏、保存到文件、创建链接和上传它们要容易得多。虽然我赞扬您希望分享您的解决方案,但请正确地做到这一点。
  • @KenWhite 我明白你的意思,我知道发布屏幕截图不是代码的好解决方案。问题是,我实际上只是想指出 16k 行 .pas 文件中我更改内容的特定位置,我希望这是某种差异视图,因此我将重点放在位置和差异上。跨度>
  • 代码中的那些位置不在过程中,也没有行号可以让您引用它们的位置?
【解决方案3】:

这是一个允许在 DPI 感知应用程序中使用 VCL 样式的单元。

VCL.Styles.DPIAware.pas

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

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

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

StyleDPIAwareness.RoundScalingFactor := False;

使用此语句,样式将缩放到 Screen.PixelsPerInch 的任何缩放因子结果。大多数样式都可以正常工作,但有些样式可能会出现一些视觉缺陷。

【讨论】:

  • TColorDialog 等系统对话框中的窗口标题缩放不正确:它们变得太高了。因此,确定和取消按钮不可见。此外,使用 uCommonFunctions 会引入许多其他单元,例如 SynEdit 相关的单元,这些单元与该单元的功能完全无关。 uCommonFunctions 使用的唯一过程是 resizeBitmap。在单元 VCL.Styles.DPIAware.pas 中复制它也许是个好主意?
猜你喜欢
  • 2019-05-15
  • 2015-07-16
  • 1970-01-01
  • 2014-07-09
  • 2017-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多