Win32gui:Windows图形界面接口模块。主要负责操作窗口切换以及窗口中元素id标签的获取
Win32api:Windows开发接口模块。主要负责模拟键盘和鼠标操作,对win32gui获取的标签进行点击/获取值/修改值等操作
Win32con:全面的库函数,提供Win32gui和Win32api需要的操作参数
Win32gui函数
FindWindow
- hld = win32gui.FindWindow(ClassName, Title)
- ClassName:窗口的类名
- Title:窗口的标题名称,即左上角的文字描述信息
- hld:返回结果为当前窗口的句柄信息
以下是使用AutoItv3抓取的Windows【另存为】窗口信息:
1 | hld = win32gui.FindWindow( "#32770" , u "另存为" ) |
>>>> Window <<<<
Title: 另存为 #这里就是上面的Title
Class: #32770 #这里就是上面的ClassName
Position: 0, 0
Size: 680, 480
Style: 0x96CC02C4
ExStyle: 0x00010101
Handle: 0x001E03A0 #这里就是上面函数返回值
SetForegroundWindow
1 | win32gui.SetForegroundWindow(hld) |
hld:为上面获取到的窗口句柄信息
主要用于激活该窗口,此时窗口会是最前面一层
在找到窗口句柄后,需要先将窗口设置为最前面一层才能模拟鼠标键盘操作当前窗口上的元素。
FindWindowEx
1 | win32gui.FindWindowEx(hld, Child, ClassName, Title) |
- hld:目标窗口的父窗口,也是上面获取到的窗口句柄信息。通过父向下找子
- Child:目标窗口的子窗口。通过子向上找父,从而找到目标窗口
- ClassName:目标窗口的类名
- Title:目标窗口的标题名称,即文字描述信息
以下是使用AutoItv3抓取的Windows【另存为】窗口的【保存】按钮信息:
1 | button = win32gui.FindWindowEx(hld, None , "Button" , None ) |
>>>> Control <<<<
Class: Button #这里就是上面的ClassName
Instance: 1
ClassnameNN: Button1
Name:
Advanced (Class): [CLASS:Button; INSTANCE:1]
ID: 1
Text: 保存(&S) #这里就是上面的Title
Position: 459, 400
Size: 88, 30
ControlClick Coords: 45, 26
Style: 0x50030000
ExStyle: 0x00000004
Handle: 0x000C12A2 #这里就是上面函数返回值
GetDlgItem
1 | button = win32gui.GetDlgItem(hld, ID ) |
- hld:目标窗口的父窗口,也是上面获取到的窗口句柄信息。通过父向下找子
- ID:目标窗口ID
上面的例子,使用ID来抓取Windows【另存为】窗口的【保存】按钮信息为:
1 | button = win32gui.GetDlgItem(hld, 1 ) |
注:需要确保,多次打开窗口时目标窗口ID是不变的,才能准确获取目标窗口句柄
SendMessage
1 | SendMessage(hWnd, Msg, wParam, lParam) |
- hWnd:接收消息的窗体句柄
- Msg:要发送的消息,这些消息都是windows预先定义好的,可以参见系统定义消息(System-Defined Messages)
- wParam:消息的wParam参数
- lParam:消息的lParam参数
注:系统定义消息中不同消息分别有相应的参数:wParam和lParam,可查询官网参数详情:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms646280(v=vs.85).aspx
以 WM_KEYDOWN消息 为例:
- wParam:虚拟键参数
- lParam:重复次数
1 | win32gui.SendMessage(hld, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0 ) |
Enter键 重复0次
【另存为】窗口点击【保存】按钮的方法:
1)方法1:发送消息目标à【保存】按钮;动作à点击
1 | win32gui.SendMessage(button, win32con.BM_CLICK) # win32con后面会解释 |
2)方法2:发送消息目标à整个窗口;动作à按键按下;动作参数àEnter键;前提à窗口聚焦默认在【保存】按钮时
1 2 | win32gui.SendMessage(hld,win32con.WM_KEYDOWN, win32con.VK_RETURN, 0 ) win32gui.PostMessage(hld,win32con.WM_KEYDOWN, win32con.VK_RETURN, 0 ) |
为什么PostMessage成功了SendMessage失败了?
PostMessage
1 | PostMessage(hWnd, Msg, wParam, lParam) |
参数和使用方法同SendMessage。
不同的是,PostMessage只将消息放入待执行消息队列,不等待处理和返回,只要放入队列即算执行完毕。而SendMessage需要等待执行处理完后,才继续,返回的是其他程序处理后的返回值。
GetWindowRect
1 | left, top, right, bottom = win32gui.GetWindowRect(hld) |
获取某元素hld位置。left, top分别指与屏幕左上角距离,right,bottom 指长和高。
返回的值分别为:
(1)窗体左边离屏幕最左边的距离;
(2)窗体顶边离屏幕最顶边的距离;
(3)窗体右边离屏幕最左边的距离;
(4)窗体底边离屏幕最顶边的距离;
MoveWindow
1 | win32gui.MoveWindow(hld, int X, int Y, int nWidth, int nHeight, BOOL bRepaint) |
移动某窗口hld到指定位置。
- x, y指与屏幕左上角距离,nWidth, nHeight 指长和高
- bRepaint:是否重绘
GetCursorPos
1 | POS = win32gui.GetCursorPos() |
获取当前鼠标点击的窗口元素的坐标
WindowFromPoint
1 | edit = win32gui.WindowFromPoint(POS) |
获取包含指定点的窗口句柄,即根据坐标获取元素句柄
以上坐标和鼠标操作应用场景:【另存为】页面修改文件名
1 2 | edit = win32gui.FindWindEx(hld, None , "Edit" , None ) edit = win32gui.GetDlgItem(hld, 1001 ) |
以上均定位失败,使用鼠标和坐标位移方法获取文件名输入框的句柄
1 2 3 4 5 6 7 8 | hld = win32gui.FindWindow(u '#32770' , u "另存为" ) win32gui.SetForegroundWindow(hld) # 为保证每次打开时目标框所在屏幕坐标不变,在这里将另存为窗口坐标和大小写死 win32gui.MoveWindow(hld, 0 , 0 , 798 , 537 , False ) win32api.SetCursorPos(( 200 , 355 )) edit = win32gui.WindowFromPoint( 200 , 355 ) win32api.SendMessage(edit, win32con.WM_SETTEXT, None , "abc" ) |
Win32api函数
SendMessage、PostMessage、GetCursorPos等win32api与win32gui均包含的函数,用法也相同。
keybd_event
1 | keybd_event(bVk, bScan, dwFlags, dwExtraInfo) |
bVk:为按键的虚拟键值,如回车键为vk_return,tab键为vk_tab其他键值具体参考如下:
(注意转换16进制)
https://msdn.microsoft.com/en-us/library/dd375731(v=vs.85).aspx
- bScan:为扫描码,一般不用设置,用0代替就行
- dwFlags:为选项标志,如果为keydown则置0即可,如果为keyup则设成"KEYEVENTF_KEYUP"
- dwExtraInfo:点击键关联的附加数据,一般置0即可
1 2 | win32api.keybd_event( 18 , 0 , 0 , 0 ) # 按下ALT键,按下后不会弹起 win32api.keybd_event( 18 , 0 , win32con.KEYEVENTF_KEYUP, 0 ) # 手动点上键结束点击 |
mouse_event
1 | mouse_event( dwFlags, dx, dy, cButtons, dwExtraInfo) |
- dwFlags:控制鼠标移动和点击按钮的各个方面。可以是下列值的某些组合:MOUSEEVENTF_ABSOLUTE,MOUSEEVENTF_LEFTDOWN,MOUSEEVENTF_MIDDLEUP等
- dx:鼠标的位置沿x轴的位移
- dy:鼠标的位置沿y轴的位移
- cButtons:与鼠标事件关联的附加值,在这里不关注
- dwExtraInfo:与鼠标事件关联的附加值,在这里不关注
1 2 | win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0 , 0 ) # 鼠标左键按下 win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0 , 0 ) # 鼠标左键拾起 |
SetCursorPos
1 | win32api.SetCursorPos(x, y) |
将光标移到屏幕坐标(x, y)处
RegOpenKey
1 | win32api.RegOpenKey(hKey, ipSubKey, phkResult) |
打开给定键,一般是打开一个现有的注册表项
- hKey:要打开键的句柄,即注册表最外层名称
- lpSubKey:要打开的项名,即项具体路径名称
- phkResult:指定一个变量,用于装载(保存)打开注册表项的一个句柄
打开endpoint注册表:
1 | endpoint_key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\Ixia Communications\Endpoint' , 0 , win32con.KEY_READ) # 最后一个参数指权限为读 |
RegQueryValueEx
1 | win32api.RegQueryValueEx(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData) |
检索一个已打开的注册表句柄中,指定的注册表键的类型和设置值。
- HKEY hKey:一个已打开项的句柄,即RegOpenKey打开的注册表项的句柄
- LPCTSTR lpValueName:要查询注册表键值的名字字符串,注册表键的名字,以空字符结束。
- LPDWORD lpReserved:未用,设为零
- LPDWORD lpType:用于装载取回数据类型的一个变量
- LPBYTE lpData:用于装载指定值的一个缓冲区
- LPDWORD lpcbData:用于装载lpData缓冲区长度的一个变量。 //一旦返回,它会设为实际装载到缓冲区的字节数
1 | install_path = win32api.RegQueryValueEx(endpoint_key, 'Installation Directory' ) |
如图最终根据键值名字' Installation Directory'得到返回值 'C:\Program Files\Ixia\Endpoint\'
RegCloseKey
1 | RegCloseKey(hKey) |
不使用时,关闭注册表。
1 | win32api.RegCloseKey(endpoint_key) |
Win32con 函数
Win32con函数一般作为win32gui win32api的参数调用。其参数命名可以这样理解:Obj_Opt
WM_COMMAND
1 | win32api.SendMessage(hld, win32con.WM_COMMAND, ( 9 << 16 ) + ctrl_id, vHandle) |
发送命令(9<<16)+ctrl_id 给窗口hld,命令要操作的窗口对象是vHandle
WM_XXXXXX:Window Message即窗口消息对应的操作
CB_GETCOUNT
1 | count = win32api.SendMessage(vHandle, win32con.CB_GETCOUNT, 0 , 0 ) |
# vHandle是一个ComboBox,通过发送CB_GETCOUNT消息获取的此下拉列表框可选值个数
CB_XXXXXX:ComboBox对象对应的操作
HKEY_LOCAL_MACHINE
1 | endpoint_key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\Ixia Communications\Endpoint' , 0 , win32con.KEY_READ) |
HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
HKEY_XXXXXX:注册表对应的操作
KEY_ALL_ACCESS
1 2 | xml_key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, 'SOFTWARE\\ Microsoft\\Office\\MSXML60', 0 , win32con.KEY_ALL_ACCESS) |
KEY_XXXXXX:理解为附加参数。在这里指打开注册表权限为全部
KEYEVENTF_KEYUP
1 | win32api.keybd_event( 69 , 0 , win32con.KEYEVENTF_KEYUP, 0 ) |
按键松开
BM_CLICK
1 | win32gui.SendMessage(btn1, win32con.BM_CLICK, None , None ) |
BM_XXXXXX:Button按键对应的操作
MOUSEEVENTF_LEFTDOWN
1 | win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0 , 0 ) |
MOUSEEVENTF_XXXXXX:鼠标对应的操作
VK_RETURN
1 | win32gui.PostMessage(nuSerWindowHandle, win32con.WM_KEYDOWN, win32con.VK_RETURN, 0 ) |
VK_XXXXXX:键盘按键操作,后跟键名称,return指回车键