Python win32gui 模块:窗口操作方法代码实例
目录
一.获取窗口句柄
1.根据类名、标题获取窗口句柄
FindWindow
FindWindowEx
2.根据坐标获取窗口句柄
WindowFromPoint
ChildWindowFromPoint
3.获取当前活动窗口(前台)句柄
4.获取具有焦点的窗口的句柄
5.枚举窗口句柄:顶层窗口句柄、子窗口句柄
EnumWindows:枚举顶层窗口句柄
EnumChildWindows:枚举指定父窗口的字窗口句柄
二.窗口操作
1.判断窗口是否存在、可见、最小化
2.获取窗口位置、尺寸信息、标题
3.设置窗口标题
4.显示或隐藏窗口
5.设置窗口焦点
6.窗口置顶(输入焦点)-前台窗口
7.窗口置顶(不改变输入焦点)
8.设置窗口位置、大小、z顺序
win32gui.SetWindowPos(hwnd, hWndInsertAfter, x, y, cx, cy, wFlags)
win32gui.MoveWindow(hwnd, x, y, nWidth, nHeight, bRepaint)
9.获取窗口的某个属性值
GetWindowLong
10.窗口闪烁
FlashWindow
11.坐标转换
将屏幕坐标转换为客户端坐标
将客户端坐标转换为屏幕坐标
三.向窗口发送消息
SendMessage
PostMessage
发送消息示例
1.关闭窗口
2.模拟按键输入
3.后台输入文字
4.模拟鼠标后台单击、双击
5.模拟鼠标移动
四.窗口绘制图形
一.获取窗口句柄
1.根据类名、标题获取窗口句柄
FindWindow
className
:窗口的类名title
:窗口的标题#标题和类名其中一个可以为None
hwnd=win32gui.FindWindow(className,title)#若匹配到,则返回顶级窗口的句柄,否则返回0
FindWindowEx
hwndParent
:父窗口的句柄。如果为0,则以桌面窗口为父窗口。hwndChildAfter
:子窗口句柄。如果为0,则从第一个子窗口开始查找。className
:窗口的类名。title
:窗口的标题hwndParent
,则从桌面窗口开始查找所有子窗口。#相对于桌面窗口,其他窗口都是桌面窗口的子窗口
#查找子窗口
hwnd=win32gui.FinWindowEx(0,0,'title','className')#标题和类名,其中一个参数可以为None
#查找指定窗口(父窗口)的子窗口
hwnd=win32gui.FinWindowEx(pHwnd,0,'title','className')
#查找指定父窗口)以及子窗口的下一级子窗口
hwnd=win32gui.FinWindowEx(pHwnd,cHwnd,'title','className')
2.根据坐标获取窗口句柄
WindowFromPoint
point
:tuple数据类型,(x,y)为相对于屏幕窗口位置的坐标。hwnd = win32gui.WindowFromPoint((x,y))
ChildWindowFromPoint
hwndParent
:父窗口的句柄。point
:tuple数据类型,(x,y)为相对于父窗口的坐标。hwnd = win32gui.ChildWindowFromPoint(pHwnd,(x,y))
3.获取当前活动窗口(前台)句柄
hwnd = win32gui.GetForegroundWindow()
4.获取具有焦点的窗口的句柄
hwnd=win32gui.GetFocus()
5.获取父窗口句柄
pHwnd=win32gui.GetParent(cHwnd)#返回子窗口的上一级窗口即父窗口的句柄
#若子窗口没有父窗口,则返回0
#若cHwnd窗口句柄不存在,则报错
6.枚举窗口句柄:顶级窗口句柄、子窗口句柄
EnumWindows:枚举顶级窗口句柄
callback
:回调函数。回调函数接收两个参数:一个窗口句柄(HWND)和一个传递给 EnumWindows
的应用程序定义值。对于每个顶级窗口,系统都会调用这个回调函数,直到回调函数返回 False
或者所有的窗口都被枚举完毕EnumWindows
函数本身并不直接使用,但它可以被用作一种方式,将额外的数据或状态传递给回调函数。传递数据:可以将任何需要的数据作为这个可选参数传递给回调函数。例如,传递一个列表或字典,以便在回调函数中收集或更新数据。
状态共享:如果需要在多个回调函数之间共享状态(比如计数或标志),可以创建一个可变对象(如列表或字典),并将其作为可选参数传递。这样,回调函数就可以修改这个对象,并且这些修改在后续的回调中可见。
控制枚举:可以使用这个参数来控制枚举的过程。例如,可以在回调函数中检查某个条件,如果满足,则通过修改这个参数来通知 EnumWindows
停止枚举。
hwndList=[]
win32gui.EnumWindows(lambda hWnd, param: param.append(hWnd), hwndList)#枚举完所有的顶级窗口后结束运行
hwndList=[]
def callback(hwnd,title):
if hwnd='xxx':
return False
titleList.append(title)#titleList列表作为可选参数传递给了 EnumWindows。回调函数 callback 将每个窗口的标题添加到这个titleList列表中
win32gui.EnumWindows(callback, titleList)#枚举到句柄为xxx的窗口时,结束运行
hwndDict={}
def callback(hwnd,title):
#IsWindow:判断指定的窗口是否打开
#IsWindowEnabled:判断窗口是否已启用
#IsWindowVisible:窗口是否可见
if win32gui.IsWindow(hwnd) and win32gui.IsWindowEnabled(hwnd):
title.update({hwnd: win32gui.GetWindowText(hwnd)})
win32gui.EnumWindows(callback, titleList)#枚举完所有的顶级窗口后结束运行
EnumChildWindows:枚举指定父窗口的子窗口句柄
callback
:回调函数。回调函数接收两个参数:一个窗口句柄(HWND)和一个传递给 EnumWindows
的应用程序定义值。对于每个顶级窗口,系统都会调用这个回调函数,直到回调函数返回 False
或者所有的窗口都被枚举完毕EnumWindows
函数本身并不直接使用,但它可以被用作一种方式,将额外的数据或状态传递给回调函数。win32gui.EnumChildWindows(pHwnd, lambda hwnd, param: param.append(hwnd), hwndList)#获取父窗口下的所有后代窗口句柄
二.窗口操作
1.判断窗口是否存在、可见、最小化
win32gui.IsWindow(hwnd)#窗口是否存在,句柄是否有效
win32gui.IsWindowVisible(hwnd)#窗口是否可见
win32gui.IsIconic(hwnd)#窗口是否最小化
2.获取窗口位置、尺寸信息、标题、类名
rect = win32gui.GetWindowRect(hwnd)
left, top, width, height = rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1]
title,className = win32gui.GetWindowText(hwnd),win32gui.GetClassName(hwnd)
3.设置窗口标题
win32gui.SetWindowText(hwnd, new_title)
4.显示或隐藏窗口
win32gui.ShowWindow(hwnd,win32con.SW_HIDE)#隐藏
win32gui.ShowWindow(hwnd,win32con.SW_SHOW)#显示
5.设置窗口焦点
win32gui.SetFocus(hwnd)# 将焦点设置到该窗口(或控件)上
6.窗口置顶(输入焦点)-前台窗口
win32gui.SetForegroundWindow(hwnd)#窗口置顶
7.窗口置顶(不改变输入焦点)
win32gui.BringWindowToTop(hwnd)
8.设置窗口位置、大小、z顺序
win32gui.SetWindowPos(hwnd, hWndInsertAfter, x, y, cx, cy, wFlags)
hwnd
:窗口句柄。hWndInsertAfter
:指定窗口 Z 顺序的位置。这可以是一个窗口句柄,表示将 hwnd
置于该窗口之后;也可以是特殊的值,如 win32con.HWND_TOP
(将窗口置于所有其他窗口之上)、win32con.HWND_BOTTOM
(将窗口置于所有其他窗口之下)等。x
和 y
:指定窗口新位置的左上角的 x 和 y 坐标。这些坐标是相对于屏幕左上角的,除非 wFlags
指定了其他坐标系。cx
和 cy
:指定窗口的新宽度和高度(以像素为单位)。wFlags
:一组标志,用于指定窗口大小和位置的各种选项。例如,win32con.SWP_NOMOVE
保持窗口位置不变,win32con.SWP_NOSIZE
保持窗口大小不变,win32con.SWP_SHOWWINDOW
显示窗口等。wFlags
:
win32con.SWP_NOMOVE
:保持窗口的当前位置(忽略 x
和 y
参数)win32con.SWP_NOSIZE:
保持窗口的当前大小(忽略 cx
和 cy
参数)win32con.SWP_NOZORDER:
保持窗口的当前 Z 顺序(忽略 hWndInsertAfter
参数)win32con.SWP_SHOWWINDOW:
显示窗口win32con.SWP_HIDEWINDOW:
隐藏窗口# 设置窗口的位置和大小
# 将窗口置于所有其他窗口之上,并移动到屏幕左上角,大小为 800x600
win32gui.SetWindowPos(hwnd, win32con.HWND_TOP, 0, 0, 800, 600, win32con.SWP_SHOWWINDOW)
win32gui.MoveWindow(hwnd, x, y, nWidth, nHeight, bRepaint)
hwnd
:要移动和调整大小的窗口的句柄。x
和 y
:指定窗口新位置的左上角的 x 和 y 坐标。这些坐标是相对于屏幕左上角的。nWidth
和 nHeight
:指定窗口的新宽度和高度(以像素为单位)。bRepaint
:一个布尔值,指定是否要重绘窗口。如果为 True
,则窗口在移动或调整大小后将被重绘;如果为 False
,则不会重绘。# 移动窗口到屏幕上的 (100, 100) 位置,并将其大小调整为 800x600 像素
win32gui.MoveWindow(hwnd, 100, 100, 800, 600, True)
9.获取窗口的某个属性值
GetWindowLong
hwnd
:窗口句柄。win32con.GWL_STYLE
、win32con.GWL_EXSTYLE
等。win32con.GWL_STYLE
: 获取窗口的样式。win32con.GWL_EXSTYLE
: 获取窗口的扩展样式。win32con.GWL_WNDPROC
: 获取窗口的过程(即窗口的消息处理函数)。win32con.GWL_HINSTANCE
: 获取与窗口关联的实例句柄。win32con.GWL_HWNDPARENT
: 如果窗口是子窗口,则获取父窗口的句柄。win32con.GWL_ID
: 获取窗口的标识符(如果窗口是子窗口)# 获取窗口的样式属性
style = win32gui.GetWindowLong(hwnd, win32con.GWL_STYLE)
10.窗口闪烁
FlashWindow
hwnd
:要闪烁的窗口的句柄。True
,窗口会反转其颜色(通常是从白色变为黑色,或从当前颜色变为其反色)并再次反转回来,产生闪烁效果。如果为 False
,则窗口不会反转颜色,但仍然会在任务栏中闪烁。wParam
: 消息的第一个参数。其含义取决于具体的消息编号。lParam
: 消息的第二个参数。其含义也取决于具体的消息编号。win32gui.FlashWindow(hwnd,True)
11.坐标转换
将屏幕坐标转换为客户端坐标
(int,int) = win32gui.ScreenToClient(hWnd,(x,y))
(int,int)=(x-winX,y-winY)#winX,winY:窗口坐标(相对于屏幕)
将客户端坐标转换为屏幕坐标
(int,int) = win32gui.ClientToScreen(hWnd,(x,y))
(int,int)=(winX+x,winY+y)#winX,winY:窗口坐标(相对于屏幕)
三.向窗口发送消息
SendMessage
hwnd
:窗口句柄。win32con
模块中定义的常量,如 win32con.WM_CLOSE
来关闭窗口wParam
: 消息的第一个参数。其含义取决于具体的消息编号。lParam
: 消息的第二个参数。其含义也取决于具体的消息编号win32con.WM_CLOSE
:请求关闭一个窗口。当窗口接收到此消息时,通常会触发关闭操作。win32con.WM_DESTROY
:一个窗口正在被销毁。此消息在窗口被销毁之前发送。win32con.WM_PAINT
:请求重绘窗口的客户区。当窗口的内容需要更新时,系统会发送此消息。win32con.WM_SETTEXT
:设置窗口的标题或文本。lParam
参数应指向包含新文本的字符串。win32con.WM_GETTEXT
:获取窗口的标题或文本。lParam
参数应指向接收文本的缓冲区,wParam
参数指定缓冲区的大小。win32con.WM_COMMAND
:用户选择了一个菜单项、点击了一个按钮或其他命令控件。wParam
参数的高位字(HIWORD)通常是控件的标识符,低位字(LOWORD)是通知码。WM_KEYDOWN
:按下键盘按键的消息。WM_KEYUP
:释放键盘按键的消息。WM_LBUTTONDOWN
:鼠标左键按下。WM_LBUTTONUP
:鼠标左键释放。WM_MOUSEMOVE
:鼠标移动。WM_PAINT
:窗口需要重绘SendMessage
是一个同步操作,它会等待消息被处理后才返回。这意味着如果你的消息处理函数执行了长时间的操作,SendMessage
也会相应地阻塞。PostMessage
win32gui.PostMessage
是进行异步消息发送的有用工具,不需要等待消息处理结果时。发送消息示例
1.关闭窗口
# 发送 WM_CLOSE 消息来请求关闭窗口
win32gui.PostMessage(hWnd, win32con.WM_CLOSE, 0, 0)
2.模拟按键输入
def backstageKBD(keyLists,hwnd):#keyLists:['A','B'],大写
keyMap = { "0": 49, "1": 50, "2": 51, "3": 52, "4": 53, "5": 54, "6": 55, "7": 56, "8": 57, "9": 58,'F1': 112, 'F2': 113, 'F3': 114, 'F4': 115, 'F5': 116, 'F6': 117, 'F7': 118, 'F8': 119,'F9': 120, 'F10': 121, 'F11': 122, 'F12': 123, 'F13': 124, 'F14': 125, 'F15': 126, 'F16': 127, "A": 65, "B": 66, "C": 67, "D": 68, "E": 69, "F": 70, "G": 71, "H": 72, "I": 73, "J": 74,"K": 75, "L": 76, "M": 77, "N": 78, "O": 79, "P": 80, "Q": 81, "R": 82, "S": 83, "T": 84,"U": 85, "V": 86, "W": 87, "X": 88, "Y": 89, "Z": 90,'BACKSPACE': 8, 'TAB': 9, 'TABLE': 9, 'CLEAR': 12,'ENTER': 13, 'SHIFT': 16, 'CTRL': 17,'CONTROL': 17, 'ALT': 18, 'ALTER': 18, 'PAUSE': 19, 'BREAK': 19, 'CAPSLK': 20, 'CAPSLOCK': 20, 'ESC': 27,'SPACE': 32, 'SPACEBAR': 32, 'PGUP': 33, 'PAGEUP': 33, 'PGDN': 34, 'PAGEDOWN': 34, 'END': 35, 'HOME': 36,'LEFT': 37, 'UP': 38, 'RIGHT': 39, 'DOWN': 40, 'SELECT': 41, 'PRTSC': 42, 'PRINTSCREEN': 42, 'SYSRQ': 42,'SYSTEMREQUEST': 42, 'EXECUTE': 43, 'SNAPSHOT': 44, 'INSERT': 45, 'DELETE': 46, 'HELP': 47, 'WIN': 91,'WINDOWS': 91, 'NMLK': 144,'NUMLK': 144, 'NUMLOCK': 144, 'SCRLK': 145}
#指定的窗口设置为前台窗口,即当前活动窗口
win32gui.SetForegroundWindow(hwnd)
#模拟按键:输入一个键或组合键
for key in keyLists:#按下
win32api.keybd_event(keyMap[key], 0, 0, 0)
#win32gui.PostMessage(hwnd, win32con.WM_KEYDOWN, keyMap[key], 0)
time.sleep(0.05)
for key in keyLists[::-1]:#松开
win32api.keybd_event(keyMap[key],0, win32con.KEYEVENTF_KEYUP, 0)
#win32gui.PostMessage(hwnd, win32con.WM_KEYUP, keyMap[key], 0)
3.后台输入文字
#指定的窗口设置为前台窗口,即当前活动窗口
win32gui.SetForegroundWindow(hwnd)
#模拟输入
for item in '哈哈哈':
win32api.PostMessage(hwnd, win32con.WM_CHAR, ord(item), 0)
4.模拟鼠标后台单击、双击
# 单击、双击,左键,右键
def click(hwnd,x,y,style='click',lr='left'):
long_position=win32api.MAKELONG(x, y) # 等价于(y) << 16 | (x)
dictLR={'left':[win32con.WM_LBUTTONDOWN,win32con.WM_LBUTTONUP],'right':[win32con.WM_RBUTTONDOWN,win32con.WM_LBUTTONUP]}
if style=='click':
# 模拟鼠标按下# 相对于句柄窗口坐标
win32api.PostMessage(hwnd, dictLR[lr][0], 0, long_position)
time.sleep(0.01)
# 模拟鼠标弹起
win32api.PostMessage(hwnd, dictLR[lr][1], 0, long_position)
time.sleep(0.01)
elif style=='Double':#双击
#先单击选中,在双击
# 模拟鼠标按下# 相对于句柄窗口坐标
win32api.PostMessage(hwnd, dictLR[lr][0], 0, long_position)
time.sleep(0.01)
# 模拟鼠标弹起
win32api.PostMessage(hwnd, dictLR[lr][1], 0, long_position)
time.sleep(0.01)
#双击
win32api.PostMessage(hwnd, win32con.WM_LBUTTONDBLCLK, win32con.MK_LBUTTON, long_position)
# win32api.PostMessage(self.hwnd, win32con.WM_LBUTTONUP, win32con.MK_LBUTTON, long_position)
time.sleep(0.01)
#单击
click(hwnd,x,y)
#双击
click(hwnd, x,y, style='Double')
#连击
for f in range(3):
self.click(hwnd, x,y)
5.模拟鼠标移动
# 发送鼠标移动消息
def move_mouse(x, y):
win32gui.PostMessage(win32gui.GetDesktopWindow(), win32con.WM_MOUSEMOVE, 0, win32gui.MAKELONG(x, y))#MAKELONG函数将x和y坐标合并成一个32位的值
time.sleep(0.01)#延迟0.01秒,可以模拟连续的鼠标移动操作。
for item in [[1,2],[3,4],[5,6]]:
move_mouse(item[0], item[1])
四.窗口绘制图形
作者:TingXiao-Ul