如何在高DPI系统中获得真实的屏幕分辨率?

WeG*_*ars 3 delphi resolution dpi delphi-xe

因此,Delphi程序不支持DPI。直到最近,当我需要具有高DPI的计算机上的真实屏幕分辨率(“让屏幕上的内容变得更容易阅读”时,Screen.Width报告的错误分辨率为150%)时,这并没有给我带来多少麻烦。建议的一些建议是使应用程序具有高DPI感知能力(XML清单),但其他警告我们这涉及很多工作!因此,由于懒惰(或缺少时间),我想知道是否有技巧来计算实际分辨率。

我想到的一个非常肮脏的技巧是创建一个DPI感知的辅助工具(微型控制台应用程序)。然后,我要做的就是调用此工具并从中获取真正的分辨率。漂亮的斯巴达人,但它应该工作。无论如何,一定有更好的方法可以做到!

Dav*_*nan 5

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.
Run Code Online (Sandbox Code Playgroud)

如果由于任何原因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