可以基于每个会话以编程方式启用/禁用DPI扩展吗?

时间:2017-06-06 19:14:02

标签: winapi graphics windows-10

我的应用程序碰巧是使用pygame用Python编写的,它包含了SDL,但我想象这可能是可能与Windows API有关的一般问题。

在我的一些Python应用程序中,即使在高分辨率下,我也希望在Windows 10下进行像素对像素控制。我希望能够确保,例如,如果我的Surface Pro 3具有2160x1440的原始分辨率,那么我可以使用这些尺寸进入全屏模式,并呈现完全相同尺寸的全屏图像。

对此的障碍是" DPI缩放"。默认情况下,在Windows'设置 - >显示,"更改文本,应用和其他项目的大小"是" 150%(推荐)"结果是我只看到了2/3的图像。我发现了如何修复这种行为......

  1. 系统范围内,将该滑块下移至100%(但对于大多数其他应用程序来说,undesirable
  2. 只针对python.exepythonw.exe,转到那些可执行文件' "属性"对话框,兼容性选项卡,然后单击"在高DPI设置和#34;上禁用显示缩放。我可以单独为我或所有用户这样做。我还可以通过以编程方式在注册表中设置适当的密钥来自动执行此过程。或者通过.exe.manifest文件(也似乎需要更改全局设置,更喜欢外部清单,可能会对其他应用程序产生副作用)。
  3. 我的问题是:在打开图形窗口之前,我可以在每个启动的基础上从里面我的程序中执行此操作吗?我或任何使用我的软件的人都不一定要为所有 Python应用程序启用此设置 - 我们可能只需要在运行特定的Python程序时使用它。我想象可能会有一个winapi调用(或者在SDL中失败的东西,由pygame包裹)可以实现这一目标,但到目前为止,我的研究已经空白了。

1 个答案:

答案 0 :(得分:8)

根据IInspectable和andlabs的评论(非常感谢),这里是我正在寻找的答案:

  import ctypes

  # Query DPI Awareness (Windows 10 and 8)
  awareness = ctypes.c_int()
  errorCode = ctypes.windll.shcore.GetProcessDpiAwareness(0, ctypes.byref(awareness))
  print(awareness.value)

  # Set DPI Awareness  (Windows 10 and 8)
  errorCode = ctypes.windll.shcore.SetProcessDpiAwareness(2)
  # the argument is the awareness level, which can be 0, 1 or 2:
  # for 1-to-1 pixel control I seem to need it to be non-zero (I'm using level 2)

  # Set DPI Awareness  (Windows 7 and Vista)
  success = ctypes.windll.user32.SetProcessDPIAware()
  # behaviour on later OSes is undefined, although when I run it on my Windows 10 machine, it seems to work with effects identical to SetProcessDpiAwareness(1)

意识级别are defined如下:

typedef enum _PROCESS_DPI_AWARENESS { 
    PROCESS_DPI_UNAWARE = 0,
    /*  DPI unaware. This app does not scale for DPI changes and is
        always assumed to have a scale factor of 100% (96 DPI). It
        will be automatically scaled by the system on any other DPI
        setting. */

    PROCESS_SYSTEM_DPI_AWARE = 1,
    /*  System DPI aware. This app does not scale for DPI changes.
        It will query for the DPI once and use that value for the
        lifetime of the app. If the DPI changes, the app will not
        adjust to the new DPI value. It will be automatically scaled
        up or down by the system when the DPI changes from the system
        value. */

    PROCESS_PER_MONITOR_DPI_AWARE = 2
    /*  Per monitor DPI aware. This app checks for the DPI when it is
        created and adjusts the scale factor whenever the DPI changes.
        These applications are not automatically scaled by the system. */
} PROCESS_DPI_AWARENESS;

2级听起来最适合我的目标,虽然1也可以,但系统分辨率/ DPI缩放没有变化。

如果之前已为当前进程调用

SetProcessDpiAwareness,那么<errorCode = -2147024891 = 0x80070005 = E_ACCESSDENIED将失败{并且包括由于注册表项或{{1而在启动进程时被系统调用文件)

相关问题