如何获取高DPI系统下的真实屏幕分辨率?

2023-12-02

因此,Delphi 程序不支持 DPI。直到最近我需要真实的屏幕分辨率时,这才让我感到困扰(当“更容易阅读屏幕上的内容”为 150% 时,Screen.Width 报告错误的分辨率)在具有高 DPI 的计算机中。一些建议是使应用程序具有高 DPI 意识(XML 清单),但其他人警告我们这涉及大量工作!因此,由于懒惰(或缺乏时间),我想知道是否有计算真实分辨率的技巧。

我想到的一个非常肮脏的技巧是创建一个支持 DPI 的配套工具(小型控制台应用程序)。我所要做的就是调用这个工具并从中获取真正的分辨率。 非常斯巴达,但应该可以。不管怎样,一定有更好的方法来做到这一点!


The Win32_DesktopMonitorWMI 类将产生该信息。

例如,使用从这里获取的代码:Delphi7:获取附加的监视器属性

{$APPTYPE CONSOLE}

uses
  SysUtils,
  ActiveX,
  ComObj,
  Variants;

function VarStrNull(VarStr: OleVariant): string;
// dummy function to handle null variants
begin
  Result := '';
  if not VarIsNull(VarStr) then
    Result := VarToStr(VarStr);
end;

procedure GetMonitorInfo;
var
  objWMIService: OleVariant;
  colItems: OleVariant;
  colItem: OleVariant;
  oEnum: IEnumvariant;
  iValue: LongWord;

  function GetWMIObject(const objectName: String): IDispatch;
  var
    chEaten: Integer;
    BindCtx: IBindCtx;
    Moniker: IMoniker;
  begin
    OleCheck(CreateBindCtx(0, BindCtx));
    OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten,
      Moniker));
    OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result));
  end;

begin
  objWMIService := GetWMIObject('winmgmts:\\localhost\root\CIMV2');
  colItems := objWMIService.ExecQuery
    ('SELECT * FROM Win32_DesktopMonitor', 'WQL', 0);
  oEnum := IUnknown(colItems._NewEnum) as IEnumvariant;
  while oEnum.Next(1, colItem, iValue) = 0 do
  begin
    Writeln('Caption      ' + VarStrNull(colItem.Caption));
    Writeln('Device ID    ' + VarStrNull(colItem.DeviceID));
    Writeln('Width        ' + VarStrNull(colItem.ScreenWidth));
    Writeln('Height       ' + VarStrNull(colItem.ScreenHeight));
    Writeln;
  end;
end;

begin
  try
    CoInitialize(nil);
    try
      GetMonitorInfo;
      Readln;
    finally
      CoUninitialize;
    end;
  except
    on E: Exception do
    begin
      Writeln(E.Classname, ': ', E.Message);
      Readln;
    end;
  end;
end.

如果由于任何原因 WMI 不可用,那么您需要一个单独的 DPI 感知进程来完成这项工作。这还需要一些 IPC。

另一个问题是最近版本的 Windows 更改了这些 WMI 类的行为。您可能需要使用不同的 WMI 查询。看这里:https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/138d387c-b222-4c9f-b3bb-c69ee890491c/problem-with-win32desktopmonitor-in-windows-8-platform?forum=windowsgeneraldevelopmentissues

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何获取高DPI系统下的真实屏幕分辨率? 的相关文章

  • Delphi如何使用其他窗体中的类型?

    抱歉 这是一个非常新手的问题 我正在对这个庞大的应用程序进行维护 它有5种不同的形式 我们将全局变量放在一个单元 uGlobal 中 但我似乎无法从数据单元 uData 访问它 我有这个 Unit uGlobal type TmyType
  • Delphi DataSnap REST 服务器从 TStream 返回 JSON 数组,而不是二进制

    我有一个与 Android 客户端通信的 REST 服务器 我将它从 XE3 ish 升级到 Berlin 其中一个服务器方法返回一个包含 jpeg 的 TStream 并且工作得很好 很高兴将图像作为二进制图像返回 升级到 Berlin
  • 如何将 JSON 字符串转换为图像?

    我有一个将图像转换为 JSON 数组的应用程序 并将其保存到 blob 字段中 function getImage String var memorystream TMemoryStream jsonArray TJSONArray beg
  • BATCH - 从 Windows 命令行获取显示分辨率并设置变量

    echo off set h wmic desktopmonitor get screenheight set w wmic desktopmonitor get screenwidth echo h echo w pause 而不是得到
  • 如何追踪“地址 00000000”的访问违规

    我知道如何创建 map 文件来在错误消息包含实际地址时跟踪访问冲突错误 但是如果错误消息说怎么办 Access violation at address 00000000 Read of address 00000000 我从哪里开始寻找这
  • 在TImageViewer中,如何获取用户点击图片的位置?

    在TImageViewer控件中 用户可以缩放或平移图片 我的问题是 当用户点击图片时 如何获取用户在图片上的点击位置 尤其是用户可以对图片进行放大 缩小或平移之后 如何获取对应的图片点击位置呢 As shown below How to
  • 如何将数据库查询的行转换为 XML 文件?

    我正在开发一个 Delphi 应用程序 该应用程序需要从一段工作中获取行并将其转换为单个 XML 文件 以便上传到第三方 Web 服务 有没有可用的组件或库可以做到这一点 如果不是 那么构建 DB2XML 转换器的最佳代码方法是什么 我注意
  • 调试器异常错误和内存超调

    我尝试运行以下代码 但它显示有关内存地址的错误 并显示一条消息 循环后 n 可能未定义 请看一看 var n max integer n integer r R1 f h0 Array of Real const h 0 00889 nip
  • 如何使用 Gmail 的 SMTP 和 Indy 10 发送电子邮件?

    我正在使用 Delphi 2009 和 svn 中最新的 Indy 10 通过 SMTP 发送电子邮件 但它不适用于 Gmail Google Apps 托管域 当我尝试发送电子邮件时 我收到 必须首先发出 STARTTLS 命令 我尝试用
  • Delphi 2010 - 从 XML 文档解码 Base64 编码图像

    我正在尝试从应用程序中的 XML 文档解码 base64 编码的 EMF 图像并将其呈现在屏幕上 但是 它似乎从未出现 如果我将 XML 文档中的数据复制 粘贴到 Notepad 中并使用Base64 Decode选项并将文件另存为 emf
  • 如何使用 FieldDefs 在运行时创建新的 SQLite 文件和表?

    我正在使用 Delphi Seattle 在全新的 SQLite 文件中创建一个全新的表 并且仅使用 FieldDefs 和非可视代码 我可以使用 ExecSQL CREATE TABLE 语法创建一个表 但不能如下所示 我得到 没有这样的
  • 打印 TDBGrid [重复]

    这个问题在这里已经有答案了 如何在不安装或下载组件的情况下打印 DBGrid OR 如何将 DBGrid 的数据放入 RichEdit 以便我可以从那里打印它 数据感知控件从 DataSource 属性获取数据 并使用它 不过 您必须手动遍
  • 如何在Delphi中显示Vista风格的气球提示?

    在输入验证时 我使用气球提示而不是消息框 我的问题是 在 Vista 上 它们具有带圆角的旧 XP 样式 而不是较新的矩形外观 我尝试使用 CreateWindowEx 创建它们并且tooltips class32或使用 SendMessa
  • 从 Delphi VCL 样式获取特定字形

    我想从 VCL 样式获取特定的位图 并将其设置为按钮上的图像 它实际上是帮助问号 在位图样式编辑器中是来自表单的 btnHelp 图像 要从 VCL 样式获取视觉元素 字形 您必须使用GetElementDetails和TCustomSty
  • 如何比较枚举类型集

    从某个时刻开始 我厌倦了编写设定条件 and or 因为对于更多的条件或更长的变量名 重新编写会变得笨拙且烦人 所以我开始写助手这样我就可以写ASet ContainsOne ceValue1 ceValue2 代替 ceValue1 in
  • H2161 重复资源[一个VCL项目可以有2个类名相同但命名空间不同的表单吗?]

    我尝试在 2 个不同的命名空间中创建具有相同类名的 2 个表单 FirstNameSpace ExampleFormName TExampleFormName SecondNameSpace ExampleFormName TExample
  • 使用 PutBlock 并将字节数组全部设置为零的 EIPHTTPProtocolExceptionPeer 异常

    使用 Delphi XE2 Update 3 我在将零字节块上传到 Azure 时遇到问题 当我说零字节时 我指的是每个元素设置为零的字节数组 不是零长度 例如 var ConInfo TAzureConnectionInfo RespIn
  • 从其可执行文件的路径获取服务名称

    我有一个可执行文件的路径 它是一个正在运行的服务应用程序 例如 C Program Files x86 Someapp somesvc exe 我想停止并启动它 为此我想我需要获取服务的名称 如下所示 this https stackove
  • Delphi - Indy - 保存 GMail 草稿

    我一直在 Delphi 下使用 Indy 通过 gmail 帐户发送消息 使用 TIdSMTP 和 TIdMessage 组件 这绝对没问题 但是 我的客户请求将消息保存到 DRAFTS 文件夹 以便他在实际发送消息之前对 以编程方式创建的
  • FireMonkey iOS RAD Studio XE2 - 在从 URL 加载的表单上显示图像

    是否可以将 TImage 放置在 iOS 的 FMX 表单上 并将图像 jpg 从 URL 加载到此 TImage 中以在 iOS 应用程序中显示 我尝试过但没有成功 任何正确方向的提示或指出都会受到赞赏 将 TButton TImageC

随机推荐