[win32&ctypes]不一样的嵌入窗口

课前准备

win32

Windows使用dwm管理窗口,可以使用user32.dll来做嵌入窗口
涉及到
user32.EnumWindows遍历窗口
user32.IsWindow user32.IsWindowVisible user32.IsWindowEnabled筛选窗口
user32.SetParent设置父窗口

python

可以用ctypes调用系统API
ctypes.windllWin系统独有,调用系统dll(即API)
ctypes.windll.user32 ctypes.windll.kernel32

为什么不用win32gui?

太大了。好像whl都有40MB,如果只需要这么一个常用功能,那么可以单独写一个API

正文

导入

import ctypes
u32 = ctypes.windll.user32 #获取dll

获取所有窗口

_all_hwnds=[]  #未处理的
_all_handles=[]#已处理的
TITLE_MAX=25   #最长标题字符数
@ctypes.CFUNCTYPE(None,ctypes.c_int)
def enum(hwnd):
    "C函数"
    _all_hwnds.append(int(hwnd))
def update_hwnd():
    global _all_hwnds,_all_handles
    _all_hwnds=[]
    _all_handles=[]
    u32.EnumWindows(enum) #更新,传入C函数
    for hwnd in _all_hwnds:#已更新
        if u32.IsWindow(hwnd) and u32.IsWindowVisible(hwnd) and u32.IsWindowEnabled(hwnd):#筛选出合适的窗口
            titlelist  = (ctypes.c_char*(TITLE_MAX+1))()#C字节串,中文是GBK编码
            u32.GetWindowTextA(hwnd,titlelist,TITLE_MAX+1)#GBK编码的串,传入hwnd,空字节串和最大长度(需+1)
            try:
                title=b""
                for w in titlelist:
                    if w!=b"\00":#\00是空
                        title+=w
                        continue
                    break
                title=title.decode("gbk")#需解码
            except:title=""
            k = {"hwnd": hwnd,"title": title}#hwnd是必要的,title用来判断窗口
            _all_handles.append(k)

嵌入

def into(title,parent):
    for h in _all_handles:
        hwnd=h["hwnd"]
        t=h["title"]
        if t==title:
            u32.SetParent(hwnd,parent)
            return

利用tkinter测试

import tkinter
import random as r
def new_subwin(parent,title=""):
    t="TOP#%d"%r.randint(1000,9999)
    new=tk.Toplevel()
    new.title(t)
    new.update()
    update_hwnd()
    into(t,parent)
    if title:new.title(title)
    return new

完整代码

import ctypes
import random as r
import tkinter as tk
u32=ctypes.windll.user32
_all_hwnds=[]
_all_handles=[]
TITLE_MAX=25
@ctypes.CFUNCTYPE(None,ctypes.c_int)
def enum(hwnd):
    _all_hwnds.append(int(hwnd))
def update_hwnd():
    global _all_hwnds,_all_handles
    _all_hwnds=[]
    _all_handles=[]
    u32.EnumWindows(enum)
    for hwnd in _all_hwnds:
        if u32.IsWindow(hwnd) and u32.IsWindowVisible(hwnd) and u32.IsWindowEnabled(hwnd):
            titlelist  = (ctypes.c_char*(TITLE_MAX+1))()
            u32.GetWindowTextA(hwnd,titlelist,TITLE_MAX+1)
            try:
                title=b""
                for w in titlelist:
                    if w!=b"\00":
                        title+=w
                        continue
                    break
                title=title.decode("gbk")
            except:title=""
            k = {"hwnd": hwnd,"title": title}
            _all_handles.append(k)
def into(title,parent):
    for h in _all_handles:
        hwnd=h["hwnd"]
        t=h["title"]
        if t==title:
            u32.SetParent(hwnd,parent)
            return
def into_func(func,parent):
    for h in _all_handles:
        hwnd=h["hwnd"]
        t=h["title"]
        if func(t):
            u32.SetParent(hwnd,parent)
            return
def into_startswith(title,parent):
    into_func(title.startswith,parent)
def into_endswith(title,parent):
    into_func(title.endswith,parent)
def into_intitle(title,parent):
    into_func(lambda t:t in title,parent)
def new_subwin(parent,title=""):
    t="TOP#%d"%r.randint(1000,9999)
    new=tk.Toplevel()
    new.title(t)
    new.update()
    update_hwnd()
    into(t,parent)
    if title:new.title(title)
    return new
if __name__ == '__main__':
    root=tk.Tk()
    root.geometry("400x400")
    winid=root.winfo_id()
    new=new_subwin(winid,"2")
    new.geometry("200x200+0+0")
    new_subwin(new.winfo_id(),"3").geometry("+0+0")
    root.deiconify()
    root.mainloop()

结尾

本文章在2021/12/12 10:54发布于CSDN
不要吝啬你的赞!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值