Source code for dragonfly.windows.win32_monitor

#
# This file is part of Dragonfly.
# (c) Copyright 2007, 2008 by Christo Butcher
# Licensed under the LGPL.
#
#   Dragonfly is free software: you can redistribute it and/or modify it
#   under the terms of the GNU Lesser General Public License as published
#   by the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   Dragonfly is distributed in the hope that it will be useful, but
#   WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#   Lesser General Public License for more details.
#
#   You should have received a copy of the GNU Lesser General Public
#   License along with Dragonfly.  If not, see
#   <http://www.gnu.org/licenses/>.
#

# pylint: disable=E0401
# This file imports a Win32-only module.

import ctypes
import logging

import win32api

from dragonfly.windows.base_monitor  import BaseMonitor
from dragonfly.windows.rectangle     import Rectangle

# Attempt to set the current process as DPI aware.  If sucessful, this will
#  ensure that the resolution is reported properly when DPI scaling is on.
#
# Note: Dragon itself sets the awareness to PROCESS_SYSTEM_DPI_AWARE, which
#  provides awareness of the DPI when the application starts, but not when
#  it changes.  Unfortunately, this cannot be changed.  When running from
#  the command line, however, the default is PROCESS_DPI_UNAWARE and can be
#  adjusted here.
#
try:
    log = logging.getLogger("monitor.init")
    value = 2  # PROCESS_PER_MONITOR_DPI_AWARE
    hresult = ctypes.windll.shcore.SetProcessDpiAwareness(value)
    hresult &= 0xffffffff
    if hresult == 0x80070057:  # E_INVALIDARG
        log.info("DPI awareness could not be set; "
                 "SetProcessDpiAwareness() received an invalid "
                 "argument: %d", value)
    elif hresult == 0x80070005:  # E_ACCESSDENIED
        log.info("DPI awareness could not be set; it has been set "
                 "already.")
except OSError:
    # Do nothing if SetProcessDpiAwareness() could not be called.
    pass


#===========================================================================
# Monitor class for storing info about a single display monitor.

[docs] class Win32Monitor(BaseMonitor): """ The monitor class used on Win32. """ #----------------------------------------------------------------------- # Class methods to create new Monitor objects.
[docs] @classmethod def get_all_monitors(cls): # Get an updated list of monitors. monitors = [] for py_handle, _, rectangle in win32api.EnumDisplayMonitors(): # Get the monitor handle. handle = py_handle.handle # Create a rectangle object representing the monitor's # dimensions and relative position. top_left_x, top_left_y, bottom_right_x, bottom_right_y = \ rectangle dx = bottom_right_x - top_left_x dy = bottom_right_y - top_left_y rectangle = Rectangle(top_left_x, top_left_y, dx, dy) # Get a new or updated monitor object and add it to the list. # Ensure that the primary monitor is first on the list. monitor = cls.get_monitor(handle, rectangle) if monitor.is_primary: monitors.insert(0, monitor) else: monitors.append(monitor) return monitors
#----------------------------------------------------------------------- # Methods that control attribute access. @property def is_primary(self): """ Whether this is the primary display monitor. :rtype: bool :returns: true or false """ monitor_info = win32api.GetMonitorInfo(self._handle) return monitor_info["Flags"] & 1 == 1 @property def name(self): """ The device name of this monitor. :rtype: str :returns: monitor name """ monitor_info = win32api.GetMonitorInfo(self._handle) return monitor_info["Device"]