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:窗口的标题
  • 功能:用于查找与指定窗口类名和窗口名称相匹配的顶级窗口。不搜索子窗口,并且不区分大小写。如果找不到匹配的窗口,返回0。
  • #标题和类名其中一个可以为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 或者所有的窗口都被枚举完毕
  • extra:可选的参数。通常用于传递数据到回调函数。可选参数对于 EnumWindows 函数本身并不直接使用,但它可以被用作一种方式,将额外的数据或状态传递给回调函数。
  • ‌extra:
  • ‌传递数据‌:可以将任何需要的数据作为这个可选参数传递给回调函数。例如,传递一个列表或字典,以便在回调函数中收集或更新数据。

  • ‌状态共享‌:如果需要在多个回调函数之间共享状态(比如计数或标志),可以创建一个可变对象(如列表或字典),并将其作为可选参数传递。这样,回调函数就可以修改这个对象,并且这些修改在后续的回调中可见。

  • ‌控制枚举‌:可以使用这个参数来控制枚举的过程。例如,可以在回调函数中检查某个条件,如果满足,则通过修改这个参数来通知 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:枚举指定父窗口的子窗口句柄
  • ‌参数‌:
  • hwnd:父窗口句柄;
  • callback:回调函数。回调函数接收两个参数:一个窗口句柄(HWND)和一个传递给 EnumWindows 的应用程序定义值。对于每个顶级窗口,系统都会调用这个回调函数,直到回调函数返回 False 或者所有的窗口都被枚举完毕
  • extra:可选的参数。通常用于传递数据到回调函数。可选参数对于 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,则不会重绘。
  • 功能:类似于SetWindowPos移动和调整窗口的大小,但不涉及窗口的 Z 顺序或其他高级选项
  • # 移动窗口到屏幕上的 (100, 100) 位置,并将其大小调整为 800x600 像素
    win32gui.MoveWindow(hwnd, 100, 100, 800, 600, True)
    9.获取窗口的某个属性值
    GetWindowLong
  • 功能:用于获取指定窗口的某个属性的值。这些属性可以控制窗口的许多方面,如样式、扩展样式、窗口过程等。
  • ‌参数‌:
  • hwnd:窗口句柄。
  • nIndex:指定要获取的窗口属性的索引。这些索引是预定义的常量,如 win32con.GWL_STYLEwin32con.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:要闪烁的窗口的句柄。
  • bInvert:布尔值,指定是否反转窗口的颜色。如果为 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:窗口句柄。
  • msg:要发送的消息编号。这通常是一个在 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
  • 参数‌、功能:与SendMessage相同
  • 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

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python win32gui 模块:窗口操作方法代码实例

    发表回复