#coding=utf-8 __author__ = 'Administrator' __doc__ = ''' pythonwin中win32gui的用法 本文件演如何使用win32gui来遍历系统中所有的顶层窗口, 并遍历所有顶层窗口中的子窗口 说明: 1.原来消息发送全部调用的SendMessage,以为优化大师内部是独立的线程处理, 但并不是,所以避免等待,直接使用PostMessage 2.自动清除。 ''' #优化大师窗口信息 YHDS_WINDOW_TITTLE = 'Wopti Utilities' YHDS_WINDOW_CLSNAME = 'TWomccMainForm' #常量 CONST_YJYH = '一键优化' CONST_YJQL = '一键清理' CONST_DIALOG_CLASS = '#32770' CONST_STATIC_CLASS = 'Static' #设置 DEBUG = False import sys import win32gui import win32con import time import subprocess from pprint import pprint from datetime import datetime def gbk2utf8(s): return s.decode('gbk').encode('utf-8') def get_window_attr(hWnd): #中文系统默认title是gb2312的编码 title = win32gui.GetWindowText(hWnd) title = gbk2utf8(title) clsname = win32gui.GetClassName(hWnd) return title,clsname def get_dialog_text(hWnd): #获取对话框的内容信息 childs = get_child_windows(hWnd) for h in childs: r_title, r_name = get_window_attr(h) if r_name != CONST_STATIC_CLASS: continue r_title = r_title.strip() if len(r_title) > 0: return r_title return '' def get_top_dialogs(): ''' 获取顶层的所有对话框 :return: ''' hWndList = get_top_windows() dialogs = [] for h in hWndList: _, clsname = get_window_attr(h) if clsname == CONST_DIALOG_CLASS: dialogs.append(h) return dialogs def show_dialog(): ''' 显示所有的对话框窗体 :param hWnd: :return: ''' show_windows(get_top_dialogs()) def show_window_attr(hWnd): ''' 显示窗口的属性 :return: ''' if not hWnd: return title,clsname = get_window_attr(hWnd) print '窗口句柄:%s ' % (hWnd) print '窗口标题:%s' % (title) print '窗口类名:%s' % (clsname) print '' def show_windows(hWndList): for h in hWndList: show_window_attr(h) def get_top_windows(): hWndList = [] win32gui.EnumWindows(lambda hWnd, param: param.append(hWnd), hWndList) return hWndList def demo_top_windows(): ''' 演示如何列出所有的顶级窗口 :return: ''' hWndList = get_top_windows() show_windows(hWndList) return hWndList def get_child_windows(parent): hWndChildList = [] win32gui.EnumChildWindows(parent, lambda hWnd, param: param.append(hWnd), hWndChildList) return hWndChildList def demo_child_windows(parent): ''' 演示如何列出所有的子窗口 :return: ''' if not parent: return hWndChildList = get_child_windows(parent) show_windows(hWndChildList) return hWndChildList def find_window(hWnd,clsname = None, title = None): if not clsname and not title: return False def notNoneCompare(l, r): if not l: return True return l == r r_title,r_clsname = get_window_attr(hWnd) return notNoneCompare(clsname, r_clsname) and notNoneCompare(title, r_title) def find_window_from_list(hWndList, clsname = None, title = None): for h in hWndList: if find_window(h, clsname, title): return h def demo_win32gui(): hWndList = demo_top_windows() assert len(hWndList) parent = hWndList[20] #这里系统的窗口好像不能直接遍历,不知道是否是权限的问题 hWndChildList = demo_child_windows(parent) print('-----top windows-----') pprint(hWndList) print('-----sub windows:from %s------' % (parent)) pprint(hWndChildList) def wait_get_top_window(clsname = None, title = None): if not clsname and not title: #无效参数 return while True: hWndList = get_top_windows() hWnd = find_window_from_list(hWndList, clsname= clsname, title= title) print('---正在搜索--- %s' % (datetime.now())) if hWnd: return hWnd #每间隔两秒钟查询一次 time.sleep(2) def get_window_by_title_filter(hWndList, nameFilter): for h in hWndList: r_title, r_name = get_window_attr(h) #标题中包含过滤器的任何一项,则认为找到 for f in nameFilter: if f in r_title: return h def autoYHDS(): #x坐标和y坐标分别是,窗口内的坐标 def click(hWnd, x, y): #低位是x,高位是y lParam = y << 15 | x win32gui.PostMessage(hWnd, win32con.WM_LBUTTONDOWN, lParam) win32gui.PostMessage(hWnd, win32con.WM_LBUTTONUP, lParam) def get_center_pos(hWnd): l, t, r, b = win32gui.GetWindowRect(hWnd) x = (r - l) / 2 y = (b - t) / 2 return x,y def click_window(hWnd): x, y = get_center_pos(hWnd) click(hWnd, x, y) def click_and_do(hWnd, const_condition, work_name='Work', work = None): print('开始%s...' % (work_name)) click_window(hWnd) #等待任务执行完成 while True: time.sleep(2) r_title, _ = get_window_attr(hWnd) if r_title == const_condition and win32gui.IsWindowEnabled(hWnd): print('%s:完成' % (work_name)) return print('正在%s,请等待...' % (work_name)) if work: work() def onekey_optimize(hWnd): click_and_do(hWnd, CONST_YJYH, CONST_YJYH) def get_ok_and_cancel(hWnd): childs = get_child_windows(hWnd) ok = get_window_by_title_filter(childs, ['确定','是']) cancel = get_window_by_title_filter(childs, ['取消','否']) assert ok and cancel return ok, cancel def onekey_clean_work(): dialogs = get_top_dialogs() filter = ['Windows优化大师', '删除多个项目'] dialog = get_window_by_title_filter(dialogs, filter) if dialog: #根据对话框的类型来点击确定还是取消 ok, cancel = get_ok_and_cancel(dialog) text = get_dialog_text(dialog) if '注册表备份' in text: click_window(cancel) else: click_window(ok) def onekey_clean(hWnd): click_and_do(hWnd, CONST_YJQL, CONST_YJQL, onekey_clean_work) ''' print('开始一键清理...') #点击开始执行一键清理操作 click_window(hWnd) time.sleep(2) #等待优化大师分析,等待分析结果 dialog = wait_get_top_window(clsname=CONST_DIALOG_CLASS, title='Windows优化大师') ok, cancel = get_ok_and_cancel(dialog) #点击确定删除扫描到的文件和文件夹 click_window(ok) time.sleep(2) #确定将所有的内容移动到垃圾箱 dialog = wait_get_top_window(clsname=CONST_DIALOG_CLASS, title='删除多个项目') ok, cancel = get_ok_and_cancel(dialog) assert ok and cancel click_window(ok) print('完成一键清理') ''' def debug(): #dialog = get_onekey_clean_yhds() #print dialog #show_dialog() dialogs = get_top_dialogs() filter = ['Windows优化大师', '删除多个项目'] dialog = get_window_by_title_filter(dialogs, filter) print get_dialog_text(dialog) sys.exit() if DEBUG: debug() hWndList = get_top_windows() yhds = find_window_from_list(hWndList, YHDS_WINDOW_CLSNAME, YHDS_WINDOW_TITTLE) if not yhds: print('优化大师应用程序未启动') sys.exit(0) childs = get_child_windows(yhds) yjyh = find_window_from_list(childs, None, CONST_YJYH) yjql = find_window_from_list(childs, None, CONST_YJQL) if not yjyh or not yjql: print('找不到优化按钮') sys.exit(0) onekey_optimize(yjyh) onekey_clean(yjql) sys.exit(0) def startYHDS(): p = subprocess.Popen('"E:\Program Files (x86)\Wopti\WoptiUtilities_CN.exe"') print('启动优化大师') h = wait_get_top_window(clsname=YHDS_WINDOW_CLSNAME, title=YHDS_WINDOW_TITTLE) assert h time.sleep(10) return p reload(sys) sys.setdefaultencoding('utf-8') #启动优化大师,优化完成后直接关闭 p = startYHDS() autoYHDS() p.kill()