2
$\begingroup$

is there a way to get the window handle value from python API?

i know about

user32 = ctypes.WinDLL('user32', use_last_error=True)
user32.GetActiveWindow()

But that's how to get the active window and not from a bpy.types.Windows API call

I can’t find a proper way to identify blender windows. basing ourselves on height and width of windows won’t work because this blender windows area always a few pixels large than what win32 is telling us

$\endgroup$

1 Answer 1

2
$\begingroup$

update

there's no garantuee you'll get the first window. if e.g. you have the preferences window open it could return that one. Since both main window & preferences have the same title "Blender"

original answer:

To get the handle of the first (main) blender window use these 2 functions. (code from bqt)

def get_process_hwnds():
    # https://stackoverflow.com/questions/37501191/how-to-get-windows-window-names-with-ctypes-in-python
    user32 = ctypes.WinDLL('user32', use_last_error=True)

    def check_zero(result, func, args):
        if not result:
            err = ctypes.get_last_error()
            if err:
                raise ctypes.WinError(err)
        return args

    if not hasattr(wintypes, 'LPDWORD'):  # PY2
        wintypes.LPDWORD = ctypes.POINTER(wintypes.DWORD)

    WindowInfo = namedtuple('WindowInfo', 'title hwnd')

    WNDENUMPROC = ctypes.WINFUNCTYPE(
        wintypes.BOOL,
        wintypes.HWND,  # _In_ hWnd
        wintypes.LPARAM, )  # _In_ lParam

    user32.EnumWindows.errcheck = check_zero
    user32.EnumWindows.argtypes = (
        WNDENUMPROC,  # _In_ lpEnumFunc
        wintypes.LPARAM,)  # _In_ lParam

    user32.IsWindowVisible.argtypes = (
        wintypes.HWND,)  # _In_ hWnd

    user32.GetWindowThreadProcessId.restype = wintypes.DWORD
    user32.GetWindowThreadProcessId.argtypes = (
        wintypes.HWND,  # _In_      hWnd
        wintypes.LPDWORD,)  # _Out_opt_ lpdwProcessId

    user32.GetWindowTextLengthW.errcheck = check_zero
    user32.GetWindowTextLengthW.argtypes = (
        wintypes.HWND,)  # _In_ hWnd

    user32.GetWindowTextW.errcheck = check_zero
    user32.GetWindowTextW.argtypes = (
        wintypes.HWND,  # _In_  hWnd
        wintypes.LPWSTR,  # _Out_ lpString
        ctypes.c_int,)  # _In_  nMaxCount

    def list_windows():
        '''Return a sorted list of visible windows.'''
        result = []

        @WNDENUMPROC
        def enum_proc(hWnd, lParam):
            if user32.IsWindowVisible(hWnd):
                pid = wintypes.DWORD()
                tid = user32.GetWindowThreadProcessId(
                    hWnd, ctypes.byref(pid))
                length = user32.GetWindowTextLengthW(hWnd) + 1
                title = ctypes.create_unicode_buffer(length)
                user32.GetWindowTextW(hWnd, title, length)
                current_pid = os.getpid()
                if pid.value == current_pid:
                    result.append(WindowInfo(title.value, hWnd))
            return True

        user32.EnumWindows(enum_proc, 0)
        return sorted(result)

    return list_windows()


def get_first_blender_window():
    process_windows = get_process_hwnds()
    return process_windows[0].hwnd
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .