当前位置 : 主页 > 编程语言 > delphi >

Delphi High DPI在自身缩放和Windows缩放之间切换

来源:互联网 收集:自由互联 发布时间:2021-06-23
我的一些客户希望能够手动扩展我的应用程序(当 Windows dpi设置为96时),因此我必须实现扩展.不幸的是,这些客户不能将Windows DPI设置为其他值并让WIndows扩展我的应用程序,因为他们使用的
我的一些客户希望能够手动扩展我的应用程序(当 Windows dpi设置为96时),因此我必须实现扩展.不幸的是,这些客户不能将Windows DPI设置为其他值并让WIndows扩展我的应用程序,因为他们使用的一些非常重要的应用程序在分辨率<>分辨率上表现不佳96 DPI.

我设法使我的Delphi 10.1应用程序规模相当好,即使在200%,但因素越高,一些比例变得“不太好看”.许多第三方组件需要特殊的缩放处理,即使这样也不能100%准确地扩展.虽然按窗口缩放的应用程序在高分辨率下看起来有点模糊,但所有比例都是100%准确,并且应用程序看起来更专业.

所以我问自己是否有可能创建一个设置,允许告诉Windows将扩展作为默认设置,并且如果客户希望扩展与当前Windows扩展不同,则只能自行扩展.此设置托管在应用程序启动时读取的可执行文件的Windows清单中.有没有办法在运行时更改它(应用程序的早期启动)?创建具有不同清单的两个可执行文件肯定不是一个好的解决方案.

谢谢你的帮助

感谢Sertac Akyuz,我找到了解决问题的方法.在包含缩放代码的单元的初始化部分中,我可以在DPI-Awareness和Non-DPI-Awareness之间切换.重要的是不要在应用程序清单中设置此设置,这可以通过提供这样的自定义清单(使用控件修饰并使用当前用户的权限运行)来实现:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
 <dependency>
   <dependentAssembly>
     <assemblyIdentity
       type="win32"
       name="Microsoft.Windows.Common-Controls"
       version="6.0.0.0"
       publicKeyToken="6595b64144ccf1df"
       language="*"
       processorArchitecture="*"/>
   </dependentAssembly>
 </dependency>
 <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
   <security>
     <requestedPrivileges>
       <requestedExecutionLevel
         level="asInvoker"
         uiAccess="false"/>
       </requestedPrivileges>
   </security>
 </trustInfo>
</assembly>

这是根据注册表项的实际代码切换:

// Set DPI Awareness depending on a registry setting
with TRegIniFile.create('SOFTWARE\' + SRegName) do
begin
  setting := readInteger('SETTINGS', 'scale', 0);
  Free;
end;
handle := LoadLibrary('shcore.dll');
if handle <> 0 then
begin
  setProcessDPIAwareness := GetProcAddress(handle, 'SetProcessDpiAwareness');
  if Assigned(setProcessDPIAwareness) then
  begin
    if setting < 2 then
      // setting <2 means no scaling vs Windows
      setProcessDPIAwareness(0)
    else
      // setting 2: 120%, 3: 140% vs. Windows
      // The actual used scaling factor multiplies by windows DPI/96
      setProcessDPIAwareness(1);
  end;
  FreeLibrary(handle);
  // Get windows scaling as Screen.PixelsPerInch was read before swiching DPI awareness
  // Our scaling routines now work with WinDPI instead of Screen.PixelsPerInch
  WinDPI:= Screen.MonitorFromWindow(application.handle).PixelsPerInch;
end;

此片段的最后一行检索当前监视器的当前DPI为screen.pixelsperinch似乎在之前初始化,并且总是返回96,就像非dpi感知应用程序一样.我在所有后续缩放计算中使用winDPI的值,它完美无缺.

网友评论