Python ctypes模块调用API函数, 制作控制电脑其他窗口工具

有时, 需要使用程序自动控制某个窗口, 或者是系统默认的窗口样式太单调, 想换一个样式。
为此, 作者使用tkinter编写了窗口控制工具, 而控制窗口又需要调用API函数。
先展示效果图:
效果图

导入ctypes模块

ctypes 是 Python 的外部函数库。它提供了与 C 兼容的数据类型,并允许调用 DLL 或共享库中的函数。导入ctypes模块, 使用如下代码即可:

from ctypes import *

调用API函数

使用ctypes的windll对象可实现调用API函数的功能。

获取窗口句柄

句柄(Handle, 简称hwnd)是一个是用来标识对象或者项目的标识符,可以用来描述窗体、文件等。获取句柄后可实现窗口的控制。

winname = input('输入窗口标题')
hwnd = windll.user32.FindWindowW(c_char_p(None),winname)
print(hwnd)
获取/设置窗口标题

需要使用GetWindowTextW, SetWindowTextW函数。set函数接收2个参数, 分别为句柄和一个字符串。

title=input('输入新标题')
windll.user32.SetWindowTextW(hwnd, title)

get函数还需要一个字符串缓冲区, 使用create_string_buffer创建。

p = create_string_buffer(256)
windll.user32.GetWindowTextW(hwnd,byref(p),256) # 获取窗口标题
title = str(p.raw,encoding='utf-16').strip('\x00') # 解码
最小化/最大化/还原

使用了ShowWindow API函数。ShowWindow函数接收2个参数, 分别为hwnd和模式类型。

# 最小化
windll.user32.ShowWindow(hwnd,SW_MINIMIZE)# 也可用windll.user32.CloseWindow(hwnd)代替
# 还原
windll.user32.ShowWindow(hwnd,SW_MAXIMIZE)
# 最大化
windll.user32.ShowWindow(hwnd,SW_RESTORE)
# 用到的常数
SW_MINIMIZE = 6
SW_MAXIMIZE = 3
SW_RESTORE = 9
关闭窗口

调用SendMessageA函数, 向窗口发送关闭消息即可。

WM_CLOSE = 0x10
windll.user32.SendMessageA(hwnd,WM_CLOSE,0,0)
更改窗体样式

窗体样式分为两类, 分别是GWL_STYLEGWL_EXSTYLE

  1. 获取样式
GWL_STYLE = -16
GWL_EXSTYLE = -20
old1=windll.user32.GetWindowLongA(hwnd,GWL_STYLE),
old2=windll.user32.GetWindowLongA(hwnd,GWL_EXSTYLE)
  1. 设置样式
    使用GWL_STYLEGWL_EXSTYLE可实现多种效果。
    注意: 使用GWL_STYLE时须在第三个参数中加入WS_VISIBLE,使窗口可用。
# 常量
WS_BORDER = 0x800000
WS_CAPTION = 0xC00000 # WS_BORDER Or WS_DLGFRAME
WS_CHILD = 0x40000000
WS_CLIPCHILDREN = 0x2000000
WS_CLIPSIBLINGS = 0x4000000
WS_POPUP = 0x80000000
WS_DLGFRAME = 0x400000
WS_DISABLED = 0x8000000
WS_OVERLAPPEDWINDOW = 0xcf0000
WS_THICKFRAME = 0x40000
WS_VISIBLE = 0x10000000

WS_EX_APPWINDOW = 0x40000
WS_EX_DLGMODALFRAME = 0x1
WS_EX_ACCEPTFILES = 0x10
WS_EX_CLIENTEDGE= 0x200
WS_EX_TOOLWINDOW = 0x80
WS_EX_WINDOWEDGE = 0x100

# 正常
windll.user32.SetWindowLongA(hwnd, GWL_STYLE, old1)
windll.user32.SetWindowLongA(hwnd, GWL_EXSTYLE, old2)
#无边框
windll.user32.SetWindowLongA(hwnd,GWL_STYLE,WS_VISIBLE+WS_CLIPSIBLINGS+WS_CLIPCHILDREN)
#细边框
windll.user32.SetWindowLongA(hwnd,GWL_STYLE,WS_VISIBLE+WS_CLIPSIBLINGS+WS_CLIPCHILDREN + WS_THICKFRAME))
#边框加粗
windll.user32.SetWindowLongA(hwnd, GWL_EXSTYLE, WS_EX_CLIENTEDGE))
# 工具窗口
windll.user32.SetWindowLongA(hwnd,GWL_EXSTYLE, WS_EX_TOOLWINDOW))
更改窗口透明度

要更改窗口透明度,首先要设置窗口的exstyle,使窗口支持透明度。
然后,调用SetLayeredWindowAttributes函数,设置窗口的透明度。
其中alpha的取值范围是0~255。

exstyle = windll.user32.GetWindowLongA(hwnd, GWL_EXSTYLE)
exstyle |= WS_EX_LAYERED  # 使窗口具有能设置透明度的样式
windll.user32.SetWindowLongA(hwnd, GWL_EXSTYLE, exstyle)
# 设置透明度
alpha = 200 # 0~255
windll.user32.SetLayeredWindowAttributes(hwnd,0,alpha,LWA_ALPHA)

常见问题

  1. 调用API函数, 如GetWindowTextW时, 需要使用create_string_buffer()创建一个字符串缓冲区对象。
  2. 调用API遇到类型错误时, 可修改函数的argtypesrestype属性,如:
from ctypes import *
windll.user32.GetWindowLongA.argtypes = [c_long,c_long]
windll.user32.GetWindowLongA.restype = c_long
windll.user32.GetWindowLongA(hwnd,GWL_STYLE)

另外, 有时需用到函数byref(), 以传递对象的引用。
3. 调用API时可能遇到编码问题, 需要将数据转换成Windows系统默认使用的ANSI编码。

总结

使用ctypes库的windll对象可实现调用各种API函数的功能。
程序窗口控制工具的完整源代码见这里: 链接

  • 7
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qfcy_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值