Не получается переместить окно (pygetwindow)

import ctypes

import pygetwindow as gw
import keyboard
import pyautogui

class Main:
    def __init__(self) -> None:
        keyboard.add_hotkey('f10', self.center_active_window)
        keyboard.wait()

    def get_taskbar_size(self):
        # Создаем структуру RECT
        rect = ctypes.wintypes.RECT()
        # Получаем дескриптор окна панели задач
        taskbar = ctypes.windll.user32.FindWindowW(u"Shell_traywnd", None)
        # Получаем размеры панели задач
        ctypes.windll.user32.GetWindowRect(taskbar, ctypes.byref(rect))
        # Возвращаем высоту панели задач
        return rect.bottom - rect.top

    def center_active_window(self):
        # Получаем активное окно
        active_window = gw.getActiveWindow()

        # Получаем размеры экрана
        screen_width, screen_height = pyautogui.size()

        # Вычитаем высоту панели задач из высоты экрана
        screen_height -= self.get_taskbar_size()

        # Проверяем, открыто ли окно "copilot"
        copilot_windows = gw.getWindowsWithTitle('copilot')
        if copilot_windows:
            # Если окно "copilot" открыто, вычитаем его ширину из ширины экрана
            screen_width -= copilot_windows[0].width

        # Вычисляем координаты для центрирования окна
        old_x = active_window._getWindowRect().left
        old_y = active_window._getWindowRect().top

        new_x = (screen_width - active_window.width) // 2
        new_y = (screen_height - active_window.height) // 2

        for px_x, px_y in (range(old_x, new_x, 7), range(old_y, new_y, 7)):  # Пробовал через zip()
            active_window.moveTo(px_x, px_y) # Вот здесь проблема, окно не перемещается


if __name__ == '__main__':
    Main()

Ответы (2 шт):

Автор решения: Armen Legran

Ваш код пытается переместить окно по одному пикселю за каждую итерацию цикла. Однако, метод moveTo из библиотеки pygetwindow может не успевать обрабатывать такое большое количество операций за короткое время.

Вместо этого, вы можете просто переместить окно на новые координаты сразу, без использования цикла.

import ctypes

import pygetwindow as gw
import keyboard
import pyautogui

class Main:
    def __init__(self) -> None:
        keyboard.add_hotkey('f10', self.center_active_window)
        keyboard.wait()

    def get_taskbar_size(self):
        # Создаем структуру RECT
        rect = ctypes.wintypes.RECT()
        # Получаем дескриптор окна панели задач
        taskbar = ctypes.windll.user32.FindWindowW(u"Shell_traywnd", None)
        # Получаем размеры панели задач
        ctypes.windll.user32.GetWindowRect(taskbar, ctypes.byref(rect))
        # Возвращаем высоту панели задач
        return rect.bottom - rect.top

    def center_active_window(self):
        # Получаем активное окно
        active_window = gw.getActiveWindow()

        # Получаем размеры экрана
        screen_width, screen_height = pyautogui.size()

        # Вычитаем высоту панели задач из высоты экрана
        screen_height -= self.get_taskbar_size()

        # Проверяем, открыто ли окно "copilot"
        copilot_windows = gw.getWindowsWithTitle('copilot')
        if copilot_windows:
            # Если окно "copilot" открыто, вычитаем его ширину из ширины экрана
            screen_width -= copilot_windows[0].width

        # Вычисляем координаты для центрирования окна
        new_x = (screen_width - active_window.width) // 2
        new_y = (screen_height - active_window.height) // 2

        # Перемещаем окно на новые координаты
        active_window.moveTo(new_x, new_y)

if __name__ == '__main__':
    Main()


→ Ссылка
Автор решения: Armen Legran

@KiryxaKart, вы пытаетесь одновременно итерироваться по двум диапазонам. Однако написанный вами код не будет работать так, как вы ожидаете. Функция range() генерирует последовательность чисел от начального значения до конечного значения с указанным шагом. Когда вы используете две функции range(), они не будут итерироваться параллельно. Вместо этого второй range() будет итерироваться для каждого элемента первого range(). Если вы хотите итерироваться по двум диапазонам одновременно, вы можете использовать функцию zip().

Ваш код пытается переместить окно на каждой итерации цикла, но это не работает, потому что moveTo не обновляет положение окна сразу. Вместо этого, он отправляет сообщение операционной системе, которое будет обработано позже.

Вы можете добавить небольшую задержку после каждого вызова moveTo, чтобы дать системе время на обработку сообщения.

import ctypes
import time

import pygetwindow as gw
import keyboard
import pyautogui

class Main:
    def __init__(self) -> None:
        keyboard.add_hotkey('f10', self.center_active_window)
        keyboard.wait()

    def get_taskbar_size(self):
        # Создаем структуру RECT
        rect = ctypes.wintypes.RECT()
        # Получаем дескриптор окна панели задач
        taskbar = ctypes.windll.user32.FindWindowW(u"Shell_traywnd", None)
        # Получаем размеры панели задач
        ctypes.windll.user32.GetWindowRect(taskbar, ctypes.byref(rect))
        # Возвращаем высоту панели задач
        return rect.bottom - rect.top

    def center_active_window(self):
        # Получаем активное окно
        active_window = gw.getActiveWindow()

        # Получаем размеры экрана
        screen_width, screen_height = pyautogui.size()

        # Вычитаем высоту панели задач из высоты экрана
        screen_height -= self.get_taskbar_size()

        # Проверяем, открыто ли окно "copilot"
        copilot_windows = gw.getWindowsWithTitle('copilot')
        if copilot_windows:
            # Если окно "copilot" открыто, вычитаем его ширину из ширины экрана
            screen_width -= copilot_windows[0].width

        # Вычисляем координаты для центрирования окна
        old_x = active_window._getWindowRect().left
        old_y = active_window._getWindowRect().top

        new_x = (screen_width - active_window.width) // 2
        new_y = (screen_height - active_window.height) // 2

        for px_x, px_y in zip(range(old_x, new_x, 7), range(old_y, new_y, 7)):
            active_window.moveTo(px_x, px_y)
            time.sleep(0.01)  # Добавляем задержку

if __name__ == '__main__':
    Main()


→ Ссылка