Получить HWND каждого окна?

Я разрабатываю приложение Python и хочу получить HWND каждого открытого окна. Мне нужно имя окна и HWND, чтобы отфильтровать список, чтобы управлять некоторыми специфическими окнами, перемещая и изменяя их размер.

Я пытался сделать это сам, просматривая информацию, но я не получил правильный фрагмент кода. Я пытался использовать этот код, но получить только заголовок каждого окна (это здорово), но мне тоже нужно HWND.

import ctypes
import win32gui
EnumWindows = ctypes.windll.user32.EnumWindows
EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
GetWindowText = ctypes.windll.user32.GetWindowTextW
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
IsWindowVisible = ctypes.windll.user32.IsWindowVisible

titles = []
def foreach_window(hwnd, lParam):
    if IsWindowVisible(hwnd):
        length = GetWindowTextLength(hwnd)
        buff = ctypes.create_unicode_buffer(length + 1)
        GetWindowText(hwnd, buff, length + 1)
        titles.append((hwnd, buff.value))
    return True
EnumWindows(EnumWindowsProc(foreach_window), 0)

for i in range(len(titles)):
    print(titles)[i]

win32gui.MoveWindow((titles)[5][0], 0, 0, 760, 500, True)

Здесь есть ошибка:

win32gui.MoveWindow((titles)[5][0], 0, 0, 760, 500, True)
 TypeError: The object is not a PyHANDLE object

person user1618465    schedule 01.02.2013    source источник
comment
SO — это не супермаркет, куда вы можете пойти со списком покупок и позволить другим делать вашу работу за вас. Что ты сделал сам?   -  person Difusio    schedule 01.02.2013
comment
@Difusio: я пытался сделать это сам, просматривая информацию, но я не получил правильный фрагмент кода. Я пробовал с этим sjohannes.wordpress.com /2012/03/23/ но я получаю только заголовок каждого окна (это здорово), но мне также нужен HWND.   -  person user1618465    schedule 01.02.2013
comment
Я имею в виду следующее: пожалуйста, опубликуйте код, который вы написали (либо на основе того, что вы нашли, либо даже скопировали) вместе с ошибками, которые вы получили или другие вещи, которые вы сделали.   -  person g.d.d.c    schedule 01.02.2013
comment
Пожалуйста, не редактируйте свой вопрос, чтобы включить исправления из ответа, потому что это делает ваш вопрос бесполезным для всех, кто придет позже и захочет его понять.   -  person abarnert    schedule 02.02.2013


Ответы (4)


Вы перепутали ctypes и win32gui.
Полученное вами hwnd получено через ctypes и является объектом LP_c_long. Вот почему win32gui.MoveWindow не принял его. Вы должны передать его

ctypes.windll.user32.MoveWindow(titles[5][0], 0, 0, 760, 500, True)

Если вы хотите использовать win32gui.MoveWindow, вы можете напрямую использовать функцию python в качестве обратного вызова.
Например,

import win32gui

def enumHandler(hwnd, lParam):
    if win32gui.IsWindowVisible(hwnd):
        if 'Stack Overflow' in win32gui.GetWindowText(hwnd):
            win32gui.MoveWindow(hwnd, 0, 0, 760, 500, True)

win32gui.EnumWindows(enumHandler, None)
person nymk    schedule 01.02.2013
comment
отличный ответ! заставил окно моего браузера прыгать через три монитора :-D - person ssc; 04.04.2014
comment
Очень полезное уточнение. Принципиально не смешивайте ctypes и win32gui. Эта простая строка может сэкономить много времени :) - person BeHappy; 17.07.2019

Ваша проблема (теперь, когда Мартино устранил вашу первоначальную проблему с отсутствием хранения значений HWND вообще) заключается в том, что вы пытаетесь смешать ctypes и win32gui.

Вы можете сделать это, если знаете, что делаете, но если нет, просто не делайте этого.

Если вы хотите получить дескрипторы окон, которые можно использовать с win32gui, используйте win32gui.EnumWindows вместо вызов необработанной функции из user32 DLL.

person abarnert    schedule 01.02.2013
comment
Для записи, я не исправил ни одной исходной проблемы. - person martineau; 25.01.2020

Чтобы получить дескрипторы всех доступных основных окон, вы передаете 0 в win32gui.EnumChildWindows, а затем проверяете, чтобы текст окна был длиннее 0 (поскольку вам нужны только фактические окна, а не скрытые/временные/всплывающие/специальные окна).

person Script and Compile    schedule 01.02.2013

Просто измените часть кода. для получения всех заголовков, поэтому он делает что-то вроде этого:

titles.append((hwnd, buff.value))

Тогда список titles будет списком кортежей, содержащих HWND и текст заголовка.

person martineau    schedule 01.02.2013
comment
Большое спасибо, но вот что происходит: (‹__main__.LP_c_long object at 0x022A9030›, u'Spotify') Я не получаю int, который позже буду использовать с win32gui.MoveWindow(hwnd, 0, 0, 760, 500, Истинный). Как я могу получить этот номер?? - person user1618465; 01.02.2013
comment
Я обновил пост с вашей помощью. Но я не могу использовать значения HWND в функции win32gui.MoveWindow(). Почему? - person user1618465; 01.02.2013
comment
Теоретически вы должны иметь возможность использовать hwnd.contents.value для получения целочисленного значения, но в моей системе это зависает по неизвестным причинам. Проблема в том, что вы смешиваете типы ctypes PyHANDLE и win32 c_long. Я думаю, что у @abarnert есть правильная идея не смешивать их. - person martineau; 02.02.2013