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

标签 delphi resolution delphi-xe dpi

因此,Delphi 程序不支持 DPI。直到最近当我需要高 DPI 的计算机中的真实屏幕分辨率( Wrong resolution reported by Screen.Width when "Make it easier to read what's on screen" is 150% )时,这才让我感到困扰。一些建议是使应用程序具有高 DPI 意识(XML list ),但其他人警告我们这涉及大量工作!因此,由于懒惰(或缺乏时间),我想知道是否有计算真实分辨率的技巧。

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

最佳答案

Win32_DesktopMonitor WMI 类将产生信息。

例如,使用取自此处的代码:Delphi7: Get attached monitor properties

{$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

关于delphi - 如何获取高DPI系统下的真实屏幕分辨率?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26100182/

相关文章:

c# - 从 C# asp.net 调用 Delphi XE6 unicode dll

css - 为不同的分辨率扩展容器 div 中的 div

delphi - 使用 Delphi XE 将通过 WinHTTP 下载的文件保存到磁盘

xml - Delphi 类到 XML 表示 :

delphi - 排序20GB数据

delphi - 在 Delphi 或 Firemonkey 中使用 CharInSet

delphi - 从vb6到delphi用WM_COPYDATA发送消息是乱码

JavaScript 日期转 Delphi TDateTime

java - JavaFX 在不同屏幕上的不同尺寸

Html 打印页面分辨率(或以像素为单位的大小)