[python-win32] Detecting when a system has multiple monitors (desktops)

Trent Nelson trent at snakebite.org
Fri Aug 27 17:24:27 CEST 2010


On 24-Aug-10 7:33 PM, Tony Cappellini wrote:
> Does anyone know how to detect if a system has multiple monitors
> (desktops) through Python?
>
> I've written a program which allows the user to open multiple
> stand-alone windows.
> When I run this program I usually drag these windows to my secondary monitor.
>
> I was to save the screen coordinates of the window locations so they
> can be restored.
>
> First, the program must detect the multiple desktops and then
> understand if the screen coordinates of those
> windows are related to the primary or secondary desktop.

You might find the following bit of code useful too.  I used to use 
MaxiVista a lot, which meant my desktop would often vary between one and 
four monitors -- nothing was more annoying than apps that would position 
themselves off-screen when I was only working off the laptop display.

So, I wrote fix_window_placements.py, which basically looks for windows 
that may have off-screen coordinates and then moves them back onto the 
main desktop.

Regards,

	Trent.

# Copyright 2010, Trent Nelson (trent at snakebite.org).
# $Id: fix_window_placements.py 6 2010-08-10 09:58:58Z Trent $

from win32gui import (
     SetFocus,
     MoveWindow,
     EnumWindows,
     GetClassName,
     GetWindowRect,
     GetWindowText,
     IsWindowEnabled,
     IsWindowVisible,
     GetDesktopWindow,
     GetWindowPlacement,
)

from ctypes import (
     windll,
     c_int,
     c_long,
     c_ulong,
     c_double,
     POINTER,
     Structure,
     WINFUNCTYPE,
)

class RECT(Structure):
     _fields_ = [
         ('left', c_long),
         ('top', c_long),
         ('right', c_long),
         ('bottom', c_long)
     ]

     def dump(self):
         return map(int, (self.left, self.top, self.right, self.bottom))

MonitorEnumProc = WINFUNCTYPE(c_int, c_ulong, c_ulong, POINTER(RECT), 
c_double)

def enum_display_monitors():
     results = []
     def _callback(monitor, dc, rect, data):
         results.append(rect.contents.dump())
         return 1
     callback = MonitorEnumProc(_callback)
     temp = windll.user32.EnumDisplayMonitors(0, 0, callback, 0)
     return results

def get_desktop_area():
     left = top = right = bottom = 0
     for r in enum_display_monitors():
         if r[0] < left:
             left = r[0]
         if r[1] < top:
             top = r[0]
         if r[2] > right:
             right = r[2]
         if r[3] > bottom:
             bottom = r[3]
     return (left, top, right, bottom)

def inside_desktop(hwnd):
     desktop = get_desktop_area()
     rect = GetWindowPlacement(hwnd)[4]
     return (
         rect[0] >= desktop[0] and
         rect[1] >= desktop[1] and
         rect[2] <= desktop[2] and
         rect[3] <= desktop[3]
     )

def enum_windows():
     results = []
     def _handler(hwnd, results):
         results.append((hwnd, GetWindowText(hwnd), GetClassName(hwnd)))
     EnumWindows(_handler, results)
     return results

def main():
     for hwnd, text, cls in enum_windows():
         if IsWindowEnabled(hwnd) and IsWindowVisible(hwnd) and text:
             if not inside_desktop(hwnd):
                 left, top, right, bottom = GetWindowPlacement(hwnd)[4]
                 width = right - left
                 height = bottom - top
                 (x, y) = GetWindowRect(GetDesktopWindow())[:2]
                 try:
                     MoveWindow(hwnd, x, y, width, height, 1)
                     print "moved '%s'" % text
                 except:
                     # Ignore windows we can't move.
                     pass

if __name__ == '__main__':
     main()




More information about the python-win32 mailing list