一招让Windows FindWindow函数更好用

  我们通过python来开发自动化或者RPA工具时,经常需要用到大名鼎鼎的pywin32库。里面有诸如sendMessage、PostMessage、FindWindow、FindwindowEx、EnumWindows等大票好用的windows系统API函数。提到Findow函数,就不得不提及它的一大缺憾:不支持基于窗口标题关键字模糊查找

  我们先来认识下今天的主角FindWindow函数。

  MSDN中的解释如下:

 

 

   简单地说,该函数检索处理顶级窗口的类名和窗口名称匹配指定的字符串,并不会搜索子窗口。

它的C++参数构成如下:

HWND FindWindowA(
  [in, optional] LPCSTR lpClassName,
  [in, optional] LPCSTR lpWindowName
);

  再来看下它的返回值:

 

 

   如果函数执行成功,它会返回包含指定类名和窗口名的窗口对应的句柄,如果失败,则返回Null。

 

  认识了该函数之后,我们再回到文章开头提到的痛点,如何让该函数支持基于窗口标题模糊查找呢?

  大体的思路是,利用EnumWindows函数得到所有顶级窗口的句柄,再通过GetClassName、GetWindowText等函数依次拿到对应窗口的类名、标题,并与我们预设的类名、窗口名关键字进行匹配,如果能关联到,返回对应的窗口句柄即可,我们需要的是这样一个人性化的FindWindow函数,姑且取名find_window_wildcard,说干就干,下面是具体的实现过程。

 1 import win32gui,re
 2 class WindowMgr:
 3     """Encapsulates some calls to the winapi for window management"""
 4 
 5     def __init__ (self):
 6         """Constructor"""
 7         self._handle = None
 8 
 9     def find_window(self, class_name, window_name=None):
10         """基于类名来查找窗口"""
11         self._handle = win32gui.FindWindow(class_name, window_name)
12 
13     def _window_enum_callback(self, hwnd, class_name_wildcard_list):
14         """传递给win32gui.EnumWindows(),检查所有打开的顶级窗口"""
15         class_name,wildcard=class_name_wildcard_list
16         if win32gui.GetClassName(hwnd)==class_name and re.match(wildcard, str(win32gui.GetWindowText(hwnd))) is not None:
17             self._handle = hwnd
18 
19     def find_window_wildcard(self, class_name,wildcard):
20         """根据类名,查找一个顶级窗口,确保其类名相符,且标题可以用正则表达式匹配对应的通配符"""
21         self._handle = None
22         win32gui.EnumWindows(self._window_enum_callback,[class_name, wildcard])
23         return self._handle
24 
25     def set_foreground(self):
26         """put the window in the foreground"""
27         win32gui.SetForegroundWindow(self._handle)
28 
29     def get_hwnd(self):
30         """return hwnd for further use"""
31         return self._handle
32 if __name__=="__main__":
33     myWindowMgr=WindowMgr()
34     '''查找一个类名为XLMAIN,窗口标题中含【银行余额】字符串的窗口,并返回它的句柄;如果没找到,返回None'''
35     excelHwnd=myWindowMgr.find_window_wildcard("XLMAIN",".*?银行余额.*?")
36     print(excelHwnd)

各位筒子赶紧试试,试完你一定会回来感谢我的,相信我~~

快来扫码关注我的公众号 获取更多爬虫、数据分析的知识!

 

posted @ 2022-01-11 23:11  NewJune  阅读(3689)  评论(0编辑  收藏  举报