Files
sanguo_vnpy_v2/scripts/qmt_relogin/childtree.py
T
claude_dev 44448480de feat(ops): 大QMT晨间自动重登工具箱——relogin全链EXIT=0实测绿
- qmt_relogin.py: 发现/外科杀/启动/凭证登录/桥应答判定(退出码0/3/4/5/6)
- 凭证安全: DPAPI加密摄取(ingest333)+运行时env注入,明文零落盘
- ui_act框架: console session UI自动化(activate/credtype/zoom/closewin/launch等op)
  +wintree/uiadump/childtree窗口透明三件套
- 机制定论: 勾「记住密码+自动登录」后强杀重启=完整登录+实例自启+桥活
  (未勾=半启动窗像主界面但实例不拉); 07:50 schtask A案上线
- 坑: SecureString=UTF-16LE; session0跑UI自动化死; cwd空串WinError123
2026-09-09 21:15:41 +08:00

73 lines
1.6 KiB
Python

# -*- coding: utf-8 -*-
"""Enumerate child windows of the QMT editor window (pid filter).
Qt usually collapses to one hwnd, but dialogs may expose buttons."""
import ctypes
import ctypes.wintypes as wt
user32 = ctypes.windll.user32
target = None
Ws = ctypes.WINFUNCTYPE(ctypes.c_bool, wt.HWND, wt.LPARAM)
@Ws
def find_cb(h, _):
global target
buf = ctypes.create_unicode_buffer(256)
user32.GetClassNameW(h, buf, 256)
return True
def cls(h):
buf = ctypes.create_unicode_buffer(256)
user32.GetClassNameW(h, buf, 256)
return buf.value
def txt(h):
buf = ctypes.create_unicode_buffer(512)
user32.GetWindowTextW(h, buf, 512)
return buf.value
def rect(h):
r = wt.RECT()
user32.GetWindowRect(h, ctypes.byref(r))
return (r.left, r.top, r.right, r.bottom)
def esc(s):
return str(s).encode("unicode_escape").decode("ascii")[:70]
# find all top-level Qt windows, then enumerate their children
qt_windows = []
@Ws
def enum_top(h, _):
if user32.IsWindowVisible(h):
if cls(h).startswith("Qt5"):
r = rect(h)
if r[0] > -30000:
qt_windows.append(h)
return True
user32.EnumWindows(enum_top, 0)
print("QT_TOP=%d" % len(qt_windows))
for q in qt_windows:
print("TOP hwnd=%s class=%s title=%s rect=%s" % (
q, esc(cls(q)), esc(txt(q)), rect(q)))
kids = []
@Ws
def enum_child(h, _):
kids.append(h)
return True
user32.EnumChildWindows(q, enum_child, 0)
print(" CHILDREN=%d" % len(kids))
for k in kids[:25]:
print(" kid hwnd=%s class=%s title=%s rect=%s" % (
k, esc(cls(k)), esc(txt(k)), rect(k)))