【问题标题】:GetSystemMetrics and TScreen returns wrong valueGetSystemMetrics 和 TScreen 返回错误值
【发布时间】:2015-02-05 08:23:50
【问题描述】:

我正在使用 Delphi XE5。我想我的笔记本电脑有问题。过了一会儿,它返回错误的值到 Screen.Width 和 GetSystemMetrics(SM_CXSCREEN) (高度相同)。我的操作系统是 Windows 7 64 位。

我的笔记本电脑的屏幕分辨率为 1920x1080 (1080p),但我的应用显示为 1280x720 (720p)。我不认为存在 DPI 问题,因为当我重新启动并在一段时间后启动时出现问题。兼容性设置也已关闭。以前有人遇到过这个问题吗?或者你知道解决方案吗?我还在下面添加了清单,但没有帮助

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    <asmv3:windowsSettings
         xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
</assembly>

这是我的编译方式

1 24 "mf.txt"

编辑:

好的,我编写了这个函数,但修复它的方法很棘手。我更喜欢 Screen.Width 返回正确的值:

function ScreenSize(var x, y: integer): boolean;
const
  ENUM_CURRENT_SETTINGS =  -1;
  ENUM_REGISTRY_SETTINGS = -2;
var
  dm: TDevMode;
begin
  Result := False;
  x := 0;
  y := 0;
  ZeroMemory(@dm, sizeof(dm));
  if EnumDisplaySettings(nil, Cardinal(ENUM_CURRENT_SETTINGS), dm) then
  begin
    Result := True;
    x := dm.dmPelsWidth;
    y := dm.dmPelsHeight;
  end else
  begin
    x := GetSystemMetrics(SM_CXSCREEN);
    y := GetSystemMetrics(SM_CYSCREEN);
  end;
end;

编辑 2:

我发现SetProcessDPIAware 解决了我的问题,但它在 XP 中不起作用

【问题讨论】:

  • 如果你有一个高 dpi 缩放设置并且你的应用程序不知道 dpi,你会得到这种行为。
  • 我的文本 DPI 缩放 150%,这就是它发生的原因。我用一个棘手的解决方案编辑了这个问题
  • 将您的答案作为答案发布,而不是将其添加到问题中。
  • 我不确定您的编辑将如何帮助您。如果在 DPI 虚拟化下运行,则无法使用非虚拟化的坐标空间。是的,您可以向用户报告这些数字,但您无能为力。
  • SetProcessDPIAware 效果很好,但不支持 XP

标签: delphi resolution getsystemmetrics


【解决方案1】:

您声明您的系统以 150% 的字体缩放比例运行。如果您的应用程序使用DPI virtualization 运行,则此虚拟化解释了您观察到的行为。请注意1920 / 1.5 = 12801080 / 1.5 = 720

对您报告的行为的唯一合理解释是该进程在 DPI 虚拟化下运行。应用 DPI 感知清单选项将停止 DPI 虚拟化。因此,清单似乎很可能没有正确链接到您的应用程序,或者清单无效。

我怀疑您的应用程序可能有两个链接到它的清单。其中第二个将被丢弃。如果您在 Delphi 项目中使用默认应用程序设置,就会发生这种情况。下一步是使用资源查看器查看链接到可执行文件的实际资源。这是查看已链接内容的可靠方法。

解决方案可能是使用 Delphi 项目选项的应用程序节点中的 自定义清单 选项并提供完整的应用程序清单。这将需要指定 comctl32 v6 以启用主题、asInvokerrequireAdministrator 选项和 DPI 感知选项。

【讨论】:

  • 我想我有正确的清单。我也尝试从 Project->Add to project 菜单中添加它。它没有帮助......
  • Project -&gt; Add 不是这样做的方法。查看应用程序节点下的项目选项。在运行时主题下选择自定义清单并提供完整的清单。
  • 大卫,当我在那里做的时候它可以工作,但我不确定我在这里松了什么。我的意思是在我选择这种方式后,我的项目中缺少什么?
  • 好吧,看看你通过启用运行时主题获得的清单。这将需要您使用资源编辑器。有很多可用的。我的猜测是默认清单将包含asInvoker 和 comctl32 v6 组件,以及产品详细信息。您需要所有这些并添加 dpi 感知选项。
  • ResourceHacker 和 XNResourceEditor 是我用过的两个
猜你喜欢
  • 2011-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-03
  • 2018-06-02
  • 2012-03-14
相关资源
最近更新 更多