python-mss icon indicating copy to clipboard operation
python-mss copied to clipboard

SetProcessDpiAwareness Failed to fit High DPI in windows if once called

Open narumi147 opened this issue 4 years ago • 0 comments

General information:

  • OS name: Windows
  • OS version: Windows 10 version 2004
  • OS architecture: 64 bits
  • Resolutions:
    • Monitor 1: 1920x1080, scale 1.25 (Laptop)
    • Monitor 2: 1920x1080, scale 1.00 (External, Main)
  • Python version: 3.7.5
  • MSS version: 6.0.0

Description of the warning/error

Once first time setting DPI awareness is not PROCESS_PER_MONITOR_DPI_AWARE=2, mss will not fit DPI scaling for all monitors.

Details

According to Microsoft Docs SetProcessDpiAwareness:

Once API awareness is set for an app, any future calls to this API will fail.

This function will return S_OK=0 only if first time to set DPI awareness, otherwise return E_ACCESSDENIED=0x80070005=-2147024891. We can print the return value to check it.

Available DPI awareness setting functions including:

  • SetProcessDpiAwareness
  • SetProcessDpiAware should equals to SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE=1)
  • SetProcessDpiAwarenessContext not tested
  • SetThreadDpiAwarenessContext not tested

In this mss package, we use SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE=2) inside __init__. However some other python packages will just call SetProcessDpiAware() during import process, like mouseinfo / pyautogui / pyscreeze. It means that only monitor which startup program has the correct DPI awareness(PROCESS_SYSTEM_DPI_AWARE) while mostly we need PROCESS_PER_MONITOR_DPI_AWARE.

Then mss uses user32.EnumDisplayMonitors to get monitor RECT and this function is affected by DPI awareness setting.

Solution

Currently I have no idea about how to avoid E_ACCESSDENIED error, one possible way is to get the real resolution of monitors regardless of DPI awareness.

According to Microsoft Docs of functions with prefix EnumDisplaySettings, e.g. EnumDisplaySettingsA, EnumDisplaySettingsExA, EnumDisplaySettingsExW, EnumDisplaySettingsW :

This API does not participate in DPI virtualization. The output given is always in terms of physical pixels, and is not related to the calling context.

I think it may be a prefer way to obtain monitor information. But I never learned Windows programming, hope anyone else can help on this problem.

Upvote & Fund

  • We're using Polar.sh so you can upvote and help fund this issue.
  • We receive the funding once the issue is completed & confirmed by you.
  • Thank you in advance for helping prioritize & fund our backlog.
Fund with Polar

narumi147 avatar Sep 16 '20 04:09 narumi147