sth0r
sth0r

Reputation: 43

GetGUIThreadInfo() with pywin32

I am trying to follow this answer and i have reached the point where a should call

GetGUIThreadInfo()

but i cannot find that in the pywin32 docomentation i am using.

What i have done so far is

import win32api
import win32gui
import win32process

test1 = win32gui.FindWindowEx(0, 0, 0, "notepad")
(test1tid, test1pid) = win32process.GetWindowThreadProcessId(test1)
test1hwndFocus = win32process.GetGUIThreadInfo(test1tid)

but the last line is compleatly made up as i cannot find the right way to call the function.

Update1:

Think i made some progress but now my struct just returns 0 when i expect some hwnd... so maybe my struct is not writen to, i think this could be because of the types in my struct, but how do i find the right types?

import win32api
import win32gui
import win32process
import ctypes

class RECT(ctypes.Structure):
    _fields_ = [
    ("left", ctypes.c_ulong),
    ("top", ctypes.c_ulong),
    ("right", ctypes.c_ulong),
    ("bottom", ctypes.c_ulong)
    ]


class GUITHREADINFO(ctypes.Structure):
    _fields_ = [
    ("cbSize", ctypes.c_ulong),
    ("flags", ctypes.c_ulong),
    ("hwndActive", ctypes.c_ulong),
    ("hwndFocus", ctypes.c_ulong),
    ("hwndCapture", ctypes.c_ulong),
    ("hwndMenuOwner", ctypes.c_ulong),
    ("hwndMoveSize", ctypes.c_ulong),
    ("hwndCaret", ctypes.c_ulong),
    ("rcCaret", RECT)
    ]

guiThreadInfoStruct = GUITHREADINFO()


ctypes.sizeof(gtitest)

test1 = win32gui.FindWindowEx(0, 0, 0, "notepad")
(test1tid, test1pid) = win32process.GetWindowThreadProcessId(test1)
ctypes.windll.user32.GetGUIThreadInfo(test1tid, guiThreadInfoStruct)
print (guiThreadInfoStruct.hwndFocus)

Update2:

I found the types here

update3:

If anyone wanna see what i used this for go look here

Upvotes: 2

Views: 389

Answers (1)

CristiFati
CristiFati

Reputation: 41147

Apparently, [MS.Docs]: GetGUIThreadInfo function is not wrapped by PyWin32, so alternative ways must be used. One of them is calling it via [Python 3.Docs]: ctypes - A foreign function library for Python (involves writing a lot of extra code).

code00.py:

#!/usr/bin/env python

import sys
import win32gui as wgui
import win32process as wproc
import win32con as wcon

import ctypes as ct
from ctypes import wintypes as wt


class GUITHREADINFO(ct.Structure):
    _fields_ = [
        ("cbSize", wt.DWORD),
        ("flags", wt.DWORD),
        ("hwndActive", wt.HWND),
        ("hwndFocus", wt.HWND),
        ("hwndCapture", wt.HWND),
        ("hwndMenuOwner", wt.HWND),
        ("hwndMoveSize", wt.HWND),
        ("hwndCaret", wt.HWND),
        ("rcCaret", wt.RECT),

    ]

    def __str__(self):
        ret = "\n" + self.__repr__()
        start_format = "\n  {0:s}: "
        for field_name, _ in self. _fields_[:-1]:
            field_value = getattr(self, field_name)
            field_format = start_format + ("0x{1:016X}" if field_value else "{1:}")
            ret += field_format.format(field_name, field_value)
        rc_caret = getattr(self, self. _fields_[-1][0])
        ret += (start_format + "({1:d}, {2:d}, {3:d}, {4:d})").format(self. _fields_[-1][0], rc_caret.top, rc_caret.left, rc_caret.right, rc_caret.bottom)
        return ret


def main(*argv):
    window_name = "Untitled - Notepad"
    hwnd = wgui.FindWindowEx(wcon.NULL, 0, wcon.NULL, window_name)
    print("'{0:s}' window handle: 0x{1:016X}".format(window_name, hwnd))
    tid, pid = wproc.GetWindowThreadProcessId(hwnd)
    print("PId: {0:d}, TId: {1:d}".format(pid, tid))

    user32_dll = ct.WinDLL("user32.dll")
    GetGUIThreadInfo = getattr(user32_dll, "GetGUIThreadInfo")
    GetGUIThreadInfo.argtypes = [wt.DWORD, ct.POINTER(GUITHREADINFO)]
    GetGUIThreadInfo.restype = wt.BOOL

    gti = GUITHREADINFO()
    gti.cbSize = ct.sizeof(GUITHREADINFO)
    res = GetGUIThreadInfo(tid, ct.byref(gti))
    print("{0:s} returned: {1:d}".format(GetGUIThreadInfo.__name__, res))
    if res:
        print(gti)


if __name__ == "__main__":
    print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    main(*sys.argv[1:])
    print("\nDone.")

Output:

e:\Work\Dev\StackOverflow\q059884688>"e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code00.py
Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 64bit on win32

'Untitled - Notepad' window handle: 0x00000000042B20D8
PId: 37192, TId: 53072
GetGUIThreadInfo returned: 1

<__main__.GUITHREADINFO object at 0x0000022649436648>
  cbSize: 0x0000000000000048
  flags: 0
  hwndActive: None
  hwndFocus: None
  hwndCapture: None
  hwndMenuOwner: None
  hwndMoveSize: None
  hwndCaret: None
  rcCaret: (0, 0, 0, 0)

Done.

Notes:

  • print data that you are working with, as it might be different what you'd expect. For example, the Notepad window title is not "notepad" like your code expects it to be, and in that case win32gui.FindWindowEx would return NULL (0).
  • I also use [ActiveState.Docs]: PyWin32 Documentation (it's old and outdated, but in most cases it's extremely helpful)

Upvotes: 2

Related Questions