ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • python 다중 모니터 창 이동
    카테고리 없음 2021. 10. 15. 09:58

    다중모니터 사용시 프로그램을 창 이동하는 프로그램입니다. 기존 스트림덱에서 사용할려고 만들었습니다.

    모니터 구분 및 창 이동을 위해서는 win32api , win32gui 가 필요합니다.

    일단 pip 로 설치합니다.

    pip install pywin32

    윈도우의 경우 설치가 안되시는 분들은 https://www.lfd.uci.edu/~gohlke/pythonlibs/#pywin32 사이트에서 python 버전과 비트에 맞는 whl 파일을 다운받아 설치하시면 됩니다.

    pip C:\경로\xxx.whl

    전체 소스입니다.

    
    from win32 import win32api, win32gui
    from operator import itemgetter
    
    class MoveMonitor():
    
        def __init__(self, parent = None):
            monitor = win32api.EnumDisplayMonitors()
            self.monitorMap = list()
    
            for info in monitor:
                # 주 모니터와 서브 모니터 구분
                if info[2][0] == 0 and info[2][1] == 0:
                    monitorType = "P"
                else :
                    monitorType = "S"
    
                self.monitorMap.append({'type': monitorType, 'handle' : info[0], 'left' : info[2][0], 'top' : info[2][1]})
    
        '''
        @ 현재 선택된 창의 타이틀과 핸들을 돌려준다.
        @ list : title, handle, left, top, width, height 
        '''
        def getActiveWindowHandle(self):
            def callback(hwnd, hwnd_list: list):
                activeTitle = win32gui.GetWindowText(win32gui.GetForegroundWindow())
                title = win32gui.GetWindowText(hwnd)
                if win32gui.IsWindowEnabled(hwnd) and win32gui.IsWindowVisible(hwnd) and title:
                    if title == activeTitle:
                        rect = win32gui.GetWindowRect(hwnd)
                        hwnd_list.append((title, hwnd, rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1]))
            output = []
            win32gui.EnumWindows(callback, output)
            return output[0]
    
        def moveWindow(self, direction):
            self.direction = direction
            tmpMonitorMap = self.monitorMap
    
            # 선택된 프로그램의 핸들값
            hwnd = self.getActiveWindowHandle()
    
            # 선택된 프로그램의 현재 모니터 위치
            thisMonitorHandle = win32api.MonitorFromWindow(hwnd[1])
    
            # 방향에 따라 list 를 정렬하여 값을 추출
            if direction == 'left':
                # left 내림차순 정렬
                sortedData = sorted(self.monitorMap, key=itemgetter('left'), reverse=False)
            elif direction == 'right':
                sortedData = sorted(self.monitorMap, key=itemgetter('left'), reverse=True)
            elif direction == 'up':
                sortedData = sorted(self.monitorMap, key=itemgetter('top'), reverse=False)
            elif direction == 'down':
                sortedData = sorted(self.monitorMap, key=itemgetter('top'), reverse=True)
    
            # 창 이동
            win32gui.MoveWindow(hwnd[1], sortedData[0]['left'], sortedData[0]['top'], hwnd[4], hwnd[5], 1)
    
    test = MoveMonitor()
    test.moveWindow('down')
    

    win32 함수에 대한 설명은 http://timgolden.me.uk/pywin32-docs 사이트를 참고하시면 됩니다.

    win32api.EnumDisplayMonitors() 함수를 이용하여 현재 시스템의 모니터 갯수와 정보(해상도, 위치) 를 확인합니다.

    결과값은 다음과 같습니다.
    [(PyHANDLE:65537, PyHANDLE:0, (0, 0, 1920, 1080)), (PyHANDLE:65539, PyHANDLE:0, (-1920, 1, 0, 1081))]

    1 : 모니터에 대한 핸들값입니다.
    2 : unknown
    3 : 위치와 해상도에 관한 값입니다. 앞의 2개 값만 사용합니다. ( left, top, width, height )
    0, 0 이 주모니터입니다. left 가 - 일 경우 주 모니터 왼쪽에 위치 한다고 보면 됩니다.
    모니터가 상하로 위치할 경우 top 의 +- 값을 보고 판단합니다.

    그리고 이동 할려고 하는 창의 정보를 가져옵니다.

    getActiveWindowHandle 함수를 이용하여 현재 포커싱된 창의 핸들값과 크기 정보를 가져옵니다.

    마지막으로 win32gui.MoveWindow 함수를 이용하여 해당 모니터의 좌측 상단을 기준으로 이동합니다.

    전 이 class 를 스트림덱에 적용하여 사용하고 있습니다.

    다음에는 큰 모니터 사용자를 위한 창 분할 기능을 만들도록 하겠습니다.

    감사합니다.

    반응형

    댓글

미래를 준비하는 개발자 by zoomer